• ベストアンサー

検索機能ソースの脆弱性に関して

以前こちらでPHPの検索機能のソースに関して質問させて頂いた者です。そのときに、作成したソースに「SQLインジェクション」の可能性があるとのご指摘を受けたのですが、下記のソースを見ていただいて、どこに脆弱性があるのか、わかる方がおられましたら是非教えていただきたく存じます。 拙い知識ながらも、本等で調べて、$_POST['key']で受け取ったデータを、get_magic_quotes_gpcの設定がOFFの場合は、addslashes関数でエスケープ処理をする設定にしたのですが、フォームの入力値に「str' or '1'='1」のようなSQLインジェクション確認用の文字を入れたり、ソースの検証を自分で行った限りでは、エラーが発見できなかったのですが、どこがまずいのでしょうか? ご教示いただけますよう、宜しくお願いいたします。 検索フォーム <form method="post" action="view.php"> <input type="text" name="key"> <input type="submit" name="search" value="検索"> </form> ログ表示PHP(view.php) $key = "%"; if (isset($_POST['key'])) { $key = (get_magic_quotes_gpc()) ? $_POST['key'] : addslashes($_POST['key']); } $sql = "SELECT * FROM shop WHERE todohuken='XX' "; if(strlen($key) > 0){ $key = str_replace(" ", " ", $key); $array = explode(" ", $key); $and = "AND "; for($i=0; $i<count($array); $i++){ $and .= "address LIKE '%$array[$i]%'"; if($i < count($array)-1){ $and .= " AND ";   }  } } mysql_select_db($database_connDB, $connDB); $Recordset1 = mysql_query($sql.$and.";", $connDB) or die(mysql_error());

  • uni51
  • お礼率100% (7/7)
  • PHP
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • galluda
  • ベストアンサー率35% (440/1242)
回答No.2
uni51
質問者

お礼

がるさん、前回に引き続きご丁寧な回答ありがとうございます。 addslashes関数を使うことの危険が認識できました。 今回はmysql_escape_string関数を使用しようと思います。 ありがとうございました。

その他の回答 (2)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

mysql_real_escape_string もあります。

参考URL:
http://www.php.net/manual/ja/function.mysql-real-escape-string.php
uni51
質問者

お礼

そうですね。 mysql_real_escape_string関数の存在は知っていたのですが、今回はPHPの4.3.XXでの運用を考えているので、mysql_escape_string関数を使用するつもりです。 ご回答いただき、ありがとうございました。

回答No.1

addslashes関数よりも、mysql_escape_string関数を利用した方が良いのではないかと思います。

uni51
質問者

お礼

ご回答ありがとうございます。 私も最近本で調べたところ、addslashes関数よりも、mysql_escape_string関数やmysql_real_escape_string関数を使用した方が良いという記述は拝見しました。 やはりaddslashes関数には脆弱性があるのですね。 参考になりました。

関連するQ&A

  • Dreamweaverで検索フォーム

    はじめまして。 DreamWeaverを使ってPHP+MySQLでWEBアプリを作っております。 ログ表示部分まで完成して、検索用のhtmlフォームから条件を指定して検索結果のみをSELECTして表示させたいのですが、「and検索やor検索」ができなくて困っています。 他に似たような質問をされている方もいますが、書いたソースが異なっているように見受けたので、投稿させていただきました。 宜しくお願いします。 検索フォーム <form method="post" action="view.php"> <input type="text" name="key"> <input type="submit" name="search" value="検索"> </form> ログ表示PHP(view.php) //検索キーワードの初期値を設定する $colname_Recordset1 = "%"; if (isset($_POST['key'])) { $colname_Recordset1 = (get_magic_quotes_gpc()) ? $_POST['key'] : addslashes($_POST['key']); } $sql = "SELECT * FROM shoplist"; if(strlen($colname_Recordset1) > 0){  $colname_Recordset2 = str_replace(" ", " ", colname_Recordset1);  $array = explode(" ", $colname_Recordset2);  $where = "where ";  for($i=0; $i<count($array); $i++){   $where .= "address like '%$array[$i]%'";   if($i < count($array)-1){    $where .= " and ";   }  } } mysql_select_db($database_connTest, $connTest); $Recordset1 = mysql_query($sql.$where, $connTest) or die(mysql_error()); $row_Recordset1 = mysql_fetch_assoc($Recordset1); $totalRows_Recordset1 = mysql_num_rows($Recordset1);

    • ベストアンサー
    • PHP
  • クラスについて

    今作っているプログラムのソースが以下のようです <html> <head> <meta http-equiv="Content-type" content="text/html; charset=UTF-8"> <input type="hidden" name="ie" value="UTF-8"> <title>7-4 MySQLクラスでのデータの表示</title> </head> <body> <b>入力された条件&nbsp;&nbsp;&nbsp;&nbsp;</b> <?php // 検索条件の表示 print "直接入力:"; print $_POST['chokusetsu']; print "&nbsp;&nbsp;&nbsp;&nbsp;読み:"; print $_POST['yomi']; print "&nbsp;&nbsp;&nbsp;&nbsp;画数:"; print $_POST['kakusuu']; print "&nbsp;&nbsp;&nbsp;&nbsp;部首:"; print $_POST['busyu']; print "&nbsp;&nbsp;&nbsp;&nbsp;の検索結果"; $search_key1 = addslashes($_POST['chokusetsu']); $search_key2 = addslashes($_POST['yomi']); $search_key3 = addslashes($_POST['kakusuu']); $search_key4 = addslashes($_POST['busyu']); //print $search_key1; //$search1にはきちんと値が入っている require_once("mysql.php");// MySQLへのID・パスワードの取得をするファイルへのアクセス //require_once("kanjiteigi.php"); //ユーザ定義関数ファイルへのアクセス function kensaku($str1,$str2,$str3,$str4){ $GLOBALS["mysql"] = new MySQL; $GLOBALS["sql"] = "SELECT * FROM tankanji WHERE kanji like '%$str1%' AND (onyomi like '%$str2%' OR kunyomi like '%$str2%') AND kakusuu like '%$str3%' AND busyu like '%$str4%'"; $GLOBALS["mysql"]->query($GLOBALS["sql"]); } // 検索条件を変数に代入してDB内を検索 kensaku($search_key1,$search_key2,$search_key3,$search_key4); //print $sql; //$mysql->query($sql); ?> //require_once("kanjiteigi.php");このような形でコメントアウトしてますが、本当はkanjiteigi.phpの中に function kensaku($str1,$str2,$str3,$str4){ $GLOBALS["mysql"] = new MySQL; $GLOBALS["sql"] = "SELECT * FROM tankanji WHERE kanji like '%$str1%' AND (onyomi like '%$str2%' OR kunyomi like '%$str2%') AND kakusuu like '%$str3%' AND busyu like '%$str4%'"; $GLOBALS["mysql"]->query($GLOBALS["sql"]); } と記述している関数をいれて参照してきたいのですが、kanjiteigi.phpにどのような記述をしていいかで悩んでいます。グローバル変数とかもややこしくて… どなたかクラスに詳しい方おられますでしょうか?? ちなみにkanjiteigi.phpの中に <?php class kanjiteigi{ // ●:ユーザ定義関数 // ○ demo1.htmlで入力する検索条件を入力し、その条件で検索するSQL文の発行し、DB内を検索 // ($str0=検索するDBのテーブル名、$str1=漢字、$str2=読み、$str3=画数、$str4=部首) // DB内を検索 var $mysql; var $sql; function kensaku($str1,$str2,$str3,$str4){ $GLOBALS["mysql"] = new MySQL; $GLOBALS["sql"] = "SELECT * FROM tankanji WHERE kanji like '%$str1%' AND (onyomi like '%$str2%' OR kunyomi like '%$str2%') AND kakusuu like '%$str3%' AND busyu like '%$str4%'"; $GLOBALS["mysql"]->query($GLOBALS["sql"]); } } ?> としてもダメでした

    • 締切済み
    • PHP
  • phpとmysqlで「あいまい検索」をしたいです。

    phpとmysqlで「あいまい検索」をしようと思い、下記サイトを参考にしましたが、 http://d.hatena.ne.jp/akihito_sado/20120602/p1 PDOを使ってlikeデータを抜き出したい場合、bindParamを使うらしいですが、 http://rasukaru55.sitemix.jp/or_kensaku.php 下記の場合どう書き直すべきでしょうか? 打ち方が悪いのか、うまく作動しません。 教えてください。 ※bindParamを使えばSQLインジェクション対策になっていると言う事でしょうか? <html> <head></head> <body> <?php //POST送信されたデータを$text1へ $text1 =@$_POST["text1"]; //SQL(テーブルから列を抽出する $sql ="SELECT 列名 FROM 表名 "; //キーワードが入力されているときはwhere以下を組み立てる if (strlen($text1)>0){ //受け取ったキーワードの全角スペースを半角スペースに変換する $text2 = str_replace(" ", " ", $text1); //キーワードを空白で分割する $array = explode(" ",$text2); //分割された個々のキーワードをSQLの条件where句に反映する $where = "WHERE "; for($i = 0; $i <count($array);$i++){ $where .= "(列名 LIKE '%$array[$i]%')"; if ($i <count($array) -1){ $where .= " AND "; } } //別カラムも同じ検索したい $where2 = " OR "; for($i = 0; $i <count($array);$i++){ $where2 .= "(2列名 LIKE '%$array[$i]%')"; if ($i <count($array) -1){ $where2 .= " AND "; } } } ?> <form method="POST" action="<?php echo $_SERVER["PHP_SELF"]?>"> <table> <tr> <td><input type="text" name="text1"></td> <td><input type="submit" value="検索" name="sub1"></td> </tr> </table> </form> <?php //組み立てたSQL分を表示する echo "<p>組み立てたSQL分: ".$sql.@$where.@$where2; ?> </body> </html>

    • ベストアンサー
    • PHP
  • 自作の検索エンジンを作成しました。AND検索 or 検索の方法をご教授いただきたい。

    こんにちは。 複数のキーワードの検索が出来ません。 ゲーム 無料 等のキーワードで検索した場合のwhere句とのコラボ組み合わせが出来ません。 $keyword=$_POST[1]; $rs=$DB->$query("SELECT * FROM data WHERE"; if($keyword){ $str = array(" ", " and ", " AND "); $keyword = str_replace($str, " ", $keyword); if(stristr($keyword, " ")){//複数キーワードの検索 $ex = explode(" ", $keyword); $count = count($exkey); for($i=0; $i<$count; $i++){ if($i!="0"){ $sql = $sql." and"; } $sql = $sql." keyword LIKE '%{$ex[$i]}%'"); } }else{//単体キーワードの検索 $sql = " keyword LIKE '%{$keyword}%'"); } } $query = $query.$sql; $result = mysql_query($query); ...結果表示 これ今のソースですけど for のあたりに何か必要ない文字とか入っていますか。 色々しているうちに無駄に複雑にしてしまっているのではと言う感じもします。

    • ベストアンサー
    • PHP
  • ユーザー定義関数について

    ユーザー定義関数について悩んでます。 ソースファイル <?php $search_key1 = addslashes($_POST['chokusetsu']); $search_key2 = addslashes($_POST['yomi']); $search_key3 = addslashes($_POST['kakusuu']); $search_key4 = addslashes($_POST['busyu']); print $search_key1; //$search1にはきちんと値が入っている require_once("mysql.php");// MySQLへのID・パスワードの取得をするファイルへのアクセス function kensaku($str1,$str2,$str3,$str4){ $GLOBALS["mysql"] = new MySQL; $GLOBALS["sql"] = "SELECT * FROM tankanji WHERE kanji like '%$str1%' AND (onyomi like '%$str2%' OR kunyomi like '%$str2%') AND kakusuu like '%$str3%' AND busyu like '%$str4%'"; } // 検索条件を変数に代入してDB内を検索 kensaku($search_key1,$search_key2,$search_key3,$search_key4); $mysql->query($sql); ?> なんですが、ユーザー定義関数を用いてDB内部を検索しようとしているのですが、$search_key1,$search_key2,$search_key3,$search_key4の値がうまく関数の中で使われなくて悩んでいます。グローバル関数とやらも自分なりには試しましたが、解決しませんでした。 ようは $search_key1 = addslashes($_POST['chokusetsu']); $search_key2 = addslashes($_POST['yomi']); $search_key3 = addslashes($_POST['kakusuu']); $search_key4 = addslashes($_POST['busyu']); の$search_key1,$search_key2,$search_key3,$search_key4を$str1,$str2,$str3,$str4に各々代入してsql文を発行しようとしてますが、うまくいかないのです。 どなたか、原因がわかる方いらっしゃるでようか??

    • ベストアンサー
    • PHP
  • checkbokとキーワード検索を組み合わせた検索

    PHP4とMySQL4.0.22を使っています。 チェックボックスとキーワードで検索結果を表示させたいと思い。 下記のようにプログラムを作成したのですが、うまく検索表示してくれません。 PHPもMySQLも初心者なため、あちこちの構文を寄せ集めたため、Parseもうまく通っていません。 どこをどういう風にすればうまくいくのか、教えていただけないでしょうか? よろしくお願いします。 ----------------------------以下PHPファイル----------- 検索フォーム 検索キーワード:<input type=text name=\"k\"value='$k' size=45 > チェックボックス <INPUT TYPE=\"CHECKBOX\" NAME=\"bumon[]\" value=\"01:河川・砂防及び海岸\">01:河川・砂防及び海岸 ・・ "; //データ検索結果の実行部分 if($sig=="kb"){ $wk ==""; if($wk<>""){ //チェックボックス $sql = "select * from tecris where"; $sql .= " ("; $i=0; foreach($_POST['bumon'] as $fr) { if ($i) { $sql .= " or "; } $sql .= "bumon = '$fr'; $i++; } $sql .= ") and "; //キーワード if($k<>""){ $xk = str_replace(" "," ",$k); $gk = explode(" ",$xk); $wk ="keyword like '%$gk[0]%'"; $i = 1; $n = count($gk) - 1; while ($i <= $n){ $wk = $wk . " and keyword like '%$gk[$i]%'"; $i++; } } //クエリの作成 $sql = $sql . $wk; };

    • 締切済み
    • PHP
  • PHP+MySQLでエスケープされたデータを格納したい。

    php.iniの設定でmagic_quotes_gpc = Offにして、 mysql_real_escape_stringで出力エスケープしたデータを MySQLに格納するとバックスラッシュが格納されない。 エスケープされたデータを格納したいです。 php.iniの設定 --------------------------------------------------------- ; Magic quotes for incoming GET/POST/Cookie data. ; magic_quotes_gpc = On magic_quotes_gpc = Off ; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. magic_quotes_runtime = Off ; Use Sybase-style magic quotes (escape ' with '' instead of '). magic_quotes_sybase = Off --------------------------------------------------------- $_POST['us_fname']には「'user'」という文字列が格納されています。 --------------------------------------------------------- $clean['us_fname'] = $_POST['us_fname']; $mysql['us_fname'] = mysql_real_escape_string($clean['us_fname']); $sql = "insert into table ( us_fname ) values ( '".$mysql['us_fname']."', ) "; --------------------------------------------------------- echo $mysql['us_fname']; で確認すると「\"user\" 」となっているんですが、 MySQLの中を確認すると「'user'」のままでシングルクォートがエスケープされていません。

    • ベストアンサー
    • PHP
  • functionの中にfunction?

    functionの中にfunctionの関数を読み込みたいのですが そのようなことはphpで可能でしょうか? ソースは以下のようになっております。 // 実行 hoge1(); hoge2(); function hoge1() { if (!$_POST["submit"]) { foreach($_POST as $k => $v) { if(get_magic_quotes_gpc()) { $v=stripslashes($v); } $v=htmlspecialchars($v); $array[$k]=$v; } extract($array); } } function hoge2() { echo <<<EOM ~~表示させる文章など~~ EOM; foreach ($array as $key => $val){ echo "<input type=\"hidden\" name=\"$key\" value=\"$val\" />\n"; } } 具体的にはhoge1のextract($array);をhoge2の$arrayに入れて foreachで出力させたいのですがどのようにすればできますでしょうか?

    • 締切済み
    • PHP
  • ログイン認証で

    ログイン認証で <? session_start(); $con=mysql_connect(localhost,***,***); mysql_select_db("***"); $passwd=addslashes($_POST['passwd']); $email=addslashes($_POST['email']); $name=addslashes($_POST['name']); $sql="select * from users where email='{$_POST['email']}' and passwd='{$_POST['passwd']}'"; $_session['name']=$name; $rs=mysql_query($sql); if(mysql_num_rows($rs)>0){ $_session['login']=1; header('location:'. "top.php"); exit; } mysql_close($con); ?> <html> <head> <title> </title> </head> 認証失敗 <br> <a href="login.php"> 戻る</a> <body> と入力したのですが、 emailとpasswdに合ったnameを違うページに表示したいのに、それができないんです・・・ ようこそ<? $_SESSION['name']?> さん<br> どこかおかしなところありますか?

    • ベストアンサー
    • PHP
  • PHPでMySQLを使った検索のプログラム

    「たったコレだけでPHPプログラミングが理解できる本」を参考にPHPでプログラムを書いていまして、 ビジネスホテルの検索機能をチェックボックス機能を余分につけて検索できないか試したのですが、 チェックボックスにチェックを入れると全く検索できず他のテキストボックスに入力するだけなら検索できます。 なんとかチェックボックスを有効にできないかいろいろなサイトを調べたり本を読んだりしましたが解決策が見つかりません。 いろいろな機能に対応できるようなプログラムを組みたいと思ったのでかなりの初心者で大変恐縮ですが、どなたかご教授お願いできないかと思っております。 あと参考になるサイトがございましたら、教えていただきたいと思っております。 何卒よろしくお願い致します。 前半省略 <form name="search_form" action="" method="post" > <input type="hidden" name="cmd" value="search" /> <table> <tr> <th>物件種別</th> <td> <input type="checkbox" name="kodawari_key[]" value="温泉" <?php if( $_REQUEST["kodawari_key"] == "温泉" ){ print( 'checked' ); } ?>/> 温泉 <input type="checkbox" name="kodawari_key[]" value="ランチ" <?php if( $_REQUEST["kodawari_key"] == "ランチ" ){ print( 'checked' ); } ?>/> ランチ<br /> <input type="checkbox" name="kodawari_key[]" value="ディナー" <?php if( $_REQUEST["kodawari_key"] == "ディナー" ){ print( 'checked' ); } ?>/> ディナー</td> </tr> <tr> <th>価格帯</th> <td> <input type="text" name="price_min" value="<?php print( htmlspecialchars( $_REQUEST["price_min"] ,ENT_QUOTES ) ) ?>" size="8"> ~ <input type="text" name="price_max" value="<?php print( htmlspecialchars( $_REQUEST["price_max"] ,ENT_QUOTES ) ) ?>" size="8"><br /> </td> </tr> <tr> <th>住所</th> <td><input type="text" name="address" value="<?php print( htmlspecialchars( $_REQUEST["address"] ,ENT_QUOTES ) ) ?>" size="20"></td> </tr> </table> <input type="submit" value="検索" class="Btn-gray button"> </form> <p>&nbsp;</p> <?php if( $_REQUEST["cmd"] == "search" ){ $pdo = new PDO("mysql:host=localhost; dbname=hotel_reservation; charset=utf8", "koredake", "koredake123", array( PDO::ATTR_EMULATE_PREPARES => false ) ); $sql = "select * from hotels where 1 = 1 "; $condition = array(); if( !empty( $_POST["kodawari_key"] )){ $sql = $sql . " and kodawari_key = :kodawari_key"; $condition["kodawari_key"] = $_REQUEST["kodawari_key"]; } if( !empty( $_REQUEST["price_min"] ) ){ $sql = $sql . " and price >= :price_min "; $condition[":price_min"] = $_REQUEST["price_min"]; } if( !empty( $_REQUEST["price_max"] ) ){ $sql = $sql . " and price <= :price_max "; $condition[":price_max"] = $_REQUEST["price_max"]; } if( !empty( $_REQUEST["address"] ) ){ $sql = $sql . " and ( pref like :pref or city like :city or address like :address ) "; $condition[":pref"] = "%{$_REQUEST["address"]}%"; $condition[":city"] = "%{$_REQUEST["address"]}%"; $condition[":address"] = "%{$_REQUEST["address"]}%"; } $statement = $pdo->prepare( $sql ); $statement->execute( $condition ); $results = $statement->fetchAll(); ?> <table border="1"> <caption>検索結果</caption> <tr> <th></th> <th>ホテル名</th> <th>宿泊料金</th> <th>住所</th> </tr> <?php foreach( $results as $result ){ ?> <tr> <td><img src="hotel/<?php print( htmlspecialchars( $result["id"], ENT_QUOTES )); ?>.png" /></td> <td><?php print( htmlspecialchars( $result["hotel_name"], ENT_QUOTES )); ?></td> <td>\<?php print( htmlspecialchars( number_format( $result["price"] ),ENT_QUOTES ) ); ?></td> <td> <?php print( htmlspecialchars( $result["pref"], ENT_QUOTES ) ); ?> <?php print( htmlspecialchars( $result["city"], ENT_QUOTES ) ); ?> <?php print( htmlspecialchars( $result["address"], ENT_QUOTES ) ); ?> </td> </tr> <?php } } ?> </table> </div> </body> </html>

    • ベストアンサー
    • MySQL