• ベストアンサー

SQLインジェンクション対策法をおしえてください。

' OR 1=1のように外部から認識されていない値をSQLクエリにする前に一度確かめる機能を加えたいのですがなかなかうまくいきません。 外部から入力されたシングルクォートをエスケープするにはどうしたらよいのでしょうか?(ソースなどあると助かります。) また、そのほかに有効な対策法などありましたら教えていただけると幸いです。 どうぞよろしくお願いいたします。

  • PHP
  • 回答数6
  • ありがとう数4

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

  • ベストアンサー
  • veax
  • ベストアンサー率75% (3/4)
回答No.4

補足質問の回答です。 $param = ctype_alnum($_POST['id_posted']) ? $_POST['id_posted'] : some_error_handling(); また、恥ずかしながら私はPHPに関しては初心者でsome_error_handling()を初めて目にします。これはいったいどのような働きを行うのでしょうか?よろしくお願いいたします。 混乱させたようで、申し訳ありません。 some_error_handling()は 何かエラー処理を実行してくださいという意味ですので、デフォルトの関数でもありませんし、拡張モジュールの関数にもありません。 ctype_alnumで書くとしたら 例えば、HTMLのフォームに <input type="text" name="user_name" value="" /> のようにあった場合、受け取り側のPHPファイルでは <?php /* 初期化 */ $username = ""; /* 配列をPOSTされた場合の処理 */ $_POST['user_name'] = (string)$_POST['user_name']; if(ctype_alnum($_POST['user_name'])===true){ $username = $_POST['user_name']; } else { /* ここでエラー処理をする、 */ /* 例えば、 再度入力画面に戻る、 *header()でリダイレクトさせる、または *include(入力画面用.php)など 又は、処理を中断する、 exit(); 又は、デフォルトの値を $usernameに代入するなどの処理を 書けばいいと思います。 (ユーザー名やパスワードの場合はデフォルト値を 入れることはないと思いますが・・・・) */ } ?>

Intel_404
質問者

お礼

回答ありがとうございました。

その他の回答 (5)

  • alioth
  • ベストアンサー率48% (13/27)
回答No.6

DBはMySQLなんですね。 mysql_escape_string は正しく使えばもちろん効果はありますが、1つの漏れもなく、ただしく使う必要があります。 ですから、PEAR をおすすめしています。 参考URLに挙げたサイトなど、PEARについて調べましたか? PEARに限らず、プレースホルダのような機能を使わずに、SQLインジェクションを防ぐことは、かなり慣れたプログラマでも困難なことです。

Intel_404
質問者

お礼

回答ありがとうございました。 すいません、DBはMySQLです。 PEARは以前から興味がありいじっていたのですがSQL Injection対策に有効とは知りませんでした。 ありがとうございました。

  • alioth
  • ベストアンサー率48% (13/27)
回答No.5

失礼ながら、まだPHP、データベース共に知識が深くないように見受けられます。 それなら、PEARのような既に実績のあるライブラリを使うことをおすすめします。 PEARのプレースホルダーの機能を使えば $query = "SELECT * FROM ACCOUNT WHERE ID = ? AND PASS = ?"; $result = $con->getAll($query, array($UID,$PASS)); のように、エスケープの処理を一切考えずにクエリを書くことができ、使用するDBに併せて、PEARが適切にサニタイジングしてくれます。 すべてのクエリにプレースホルダを使うと決めてプログラミングするとSQLインジェクションについては、回避できます。

参考URL:
http://kamakura.cool.ne.jp/oppama/oswa/phppeardb.html
Intel_404
質問者

お礼

Pearですか、挑戦してみたいと思います。 ありがとうございました。

Intel_404
質問者

補足

関数のmysql_escape_stringとはSQL Injection に有効なのでしょうか?

  • veax
  • ベストアンサー率75% (3/4)
回答No.3

エスケープでは対処しきれない場合があります。 個々のフィールドに対するctypeやcastを使う方法もいいかもしれません。 例えばIDカラムには通常数字が入り、 ポストされる文字も数値を期待しているのであれば $param = ctype_digit($_POST['id_posted']) ? $_POST['id_posted'] : some_error_handling(); 又は、 $param = (int)$_POST['id_posted'] などでも出来ると思います、 文字列ならば、単純に 使用不可能の文字を発見した時点で もう一度入力画面に戻るかデフォルトのクエリーを 発行するのがいいのでは?この場合は"'"

Intel_404
質問者

補足

回答ありがとうございます。 $param = ctype_digit($_POST['id_posted']) ? $_POST['id_posted'] : some_error_handling();と書いていただきましたが、もし渡される値が英数字の場合はどうなるのでしょうか? 私なりに調べ考えてみた結果以下のようになりました。 $param = ctype_alnum($_POST['id_posted']) ? $_POST['id_posted'] : some_error_handling(); また、恥ずかしながら私はPHPに関しては初心者でsome_error_handling()を初めて目にします。これはいったいどのような働きを行うのでしょうか?よろしくお願いいたします。

回答No.2

参考URLにいろいろと議論されていますので、 覗いてみてはいかがでしょう。 あと、以下の記事が参考になるかと・・・ http://www.atmarkit.co.jp/fsecurity/special/30xss/xss01.html

参考URL:
http://vsug.jp/tabid/63/forumid/56/postid/537/view/topic/Default.aspx
  • Bonjin
  • ベストアンサー率43% (418/971)
回答No.1

通常は\がエスケープ文字になりますが、DBMSによって異なる場合があります。使っているDBMSのエスケープ文字について調べてみてください。

Intel_404
質問者

補足

回答ありがとうございます。 \がエスケープ文字の場合、' OR 1=1では攻撃できませんが、\' OR 1=1 では攻撃されてしまいます。 どうすればいいのでしょうか?

関連するQ&A

  • SQLインジェクション対策(クオーテーション関連

    PHP Version 5.4.7の環境にて。 SQLite3::escapeStringを使って、 SQLインジェクション対策をしようと考えています。 HTMLの<form>からPOSTで値を受け取り、 その値をSQL文に入れ込み、 そのクエリ(※ちなみに、INSERTのみです。)をSQLite3のDBに対して行う、 なんてことをする際の、 SQLインジェクション対策として、お考え下さい。 POSTで受け取る値に入っていたら危険なものとして、 「シングルクオーテーション」が、まず、挙げられるかと思います。 「'」 ←これです。 さて、「"」 ←こちらはダブルクオーテーションですが、 こちらのダブルの方はエスケープする必要は無いのでしょうか? (例)※wikipediaより SELECT * FROM users WHERE name = '(入力値)'; SELECT * FROM users WHERE name = 't' OR 't' = 't'; → このSQL文では条件が常に真となるため、 nameカラムの値にかかわらず、全レコードが選択される。 → ということで、入力値に、 エスケープされていない「シングルクオーテーション」をそのまま使うのはNG。 ここまではOKです。 では、次に、ダブルクオーテーション版で、 SELECT * FROM users WHERE name = "(入力値)"; SELECT * FROM users WHERE name = "t" OR "t" = "t"; こちらはどうなのでしょうか? (シングルをダブルに変えただけですが。) ---------- ちなみに、 SQLite3::escapeString にて、 (1) $var = "Let's"; //←シングルクオーテーション $db = new SQLite3(':memory:'); $escaped_var = $db->escapeString($var); echo $escaped_var; //Let''s と表示される (「 ' 」が1つ追加される。) (2) $var = 'Let"s'; //←ダブルクオーテーション $db = new SQLite3(':memory:'); $escaped_var = $db->escapeString($var); echo $escaped_var; //Let"s と表示される (何も追加されず。) というように、 シングルクオーテーションはエスケープされるが、 ダブルクオーテーションの方ではエスケープされませんでした。 これは、つまり、 ダブルクオーテーションの方は危険視されていない、 ということだと思いますが、 でも、本当にダブルクオーテーションをエスケープせずに、 そのまま、SQL文につっこんでも大丈夫なのでしょうか?

    • ベストアンサー
    • PHP
  • sqlに記述できない文字

    いつもお世話になっております。 WEB画面から入力された項目を対象にPostgresに検索しに行っているのですが、シングルクォート(')が入っていた場合、エラーになってしまいました。 JavaからSQLを生成し、Postgresに接続しているのですが、シングルクォートを検索させるにはどうするのが良いでしょうか。 またSQLに記述できない文字は、シングルクォートのほかに何かありますでしょうか。 よろしくお願いします。

  • 正規表現でSQLのエスケープ

    C# 2.0 & SQLServer2000 でプログラムを作成しています。 通常のADOではなく、サードパーティーのDBコンポーネントを使ってDB周りはやっているのですが、その際に SQL 文は自分でエスケープしてやる必要があることに後から気付き、正規表現でSQL文をまとめてエスケープすることはできないかと考えています。 正規表現を使って実現したい事は以下です。 ・文字列中の ' (シングルクォート)を '' (シングルクォート2つ)に置換 ・ただし、 where field = 'xxxx' のように文字列を間に入れている場合の ' は置換しない WEBなどで調べても見つかりませんでした。どなたか正規表現に強い方、教えてください。

  • SQLインジェクションが発生する理由

    初めての質問です。よろしくお願いします。 今現在、SQLインジェクションというものが問題になっていますよね いろいろなサイトを回って調べて見たのですが、具体的な対策として、「'(シングルクォーテーション)」などの特殊文字を確実にエスケープすること、くらいしか対策が書かれておりません。 特殊文字のエスケープさえしっかりしておけばSQLインジェクションは発生しない、という印象を受けたのですが、SQLインジェクションがおきてしまったサイトではエスケープ処理をしていなかったということなのでしょうか? それとも、エスケープ処理をしていても何らかの方法で不正なSQLの命令を実行されてしまうのでしょうか? どうにもわからなくて困っているので、どうかよろしくお願いいたします。

  • SQLインジェクション対策

    Webアプリにて入力フォームからのSQLインジェクション対策を行いたいと思っているのですが その1つとしてpreparedstatement SQLを使用することを考えています。 これを使用すればシングルクォーテーションを使った 悪意のあるSQL文を挿入されることが防げると思うのですが他に何か考慮することって あるのでしょうか。

    • ベストアンサー
    • Java
  • [ACCESS97]SQLの書き方

    グラフのレコードソースにクエリ・SQLを使用しています。データ入力チェックに使おうと思っています。妙なデータがはいった場合、グラフが乱れるのではないかと。 ソートは日付でしています。 それで、100レコードずつを順番に表示していきたいのですが、top値 だと最初からいくつ、、としか指定できません。これを、レコードの途中の任意の位置から取るにはどうしたらいいのでしょうか? IDとかのようにユニークな値でソートしているのであれば、大小関係で一発ですが、同じ値がいくつも存在する日付なもので困っています。 日付でソートしたものを配列に入れる、もしくは一度テーブルに書き出す等も考えているのですが、SQLでできたら助かります。 よろしくお願いします。

  • PDOを使用し複数キーワードでOR条件のDB検索

    PDOを使用した複数キーワードでOR条件のDB検索をしたいです。 対象レコード件数が少ないので「LIKE '%hoge%'」で書こうと思うのですが下記の様にループで 書くしかないのでしょうか。 シングルクオートなどエスケープの処理を別で考えなければならず面倒なソースになってしまい、 他に良い方法が有りそうだけど、、と考えています。 初歩的な疑問ですが宜しくお願いします。 $serch_input = array('hoge','foo','""""') $input[] = prode(" " ,$serch_input) $sql = 'SELECT * FROM hoge WHERE '; foreach($input as $w) { $sql .= 'OR hoge.text LIKE "%' . $w . '%"'; } $result = connect()->query($sql); return $result;

    • ベストアンサー
    • PHP
  • CakePHPでquery()を使うときについて

    CakePHP バージョン1.3.7です。 CakePHPでqueryを使ってSQL文を書くときなんですが 公式サイトに以下のように App::import('Sanitize'); $sql = "SELECT * FROM users WHERE id = $id"; $sql = Sanitize::clean($sql); サニタイズをしなさいとありますが、 上記の$idの部分がdate型で $sql = "SELECT * FROM users WHERE date = '2011-05-16'"; みたいなときシングルクオートがエスケープされてクエリが通らないのはどうやって解決すればいいんでしょうか?

    • ベストアンサー
    • PHP
  • レコードソースにSQLを設定

    accessのレコードソースプロパティにテーブルやクエリではなく直接SQLを指定して条件にhitするデータだけ表示する方法がわからずに困っています。 SQLはメインフォームで入力した変数を持っています。 作業を効率化するために絶対に必要な機能なのでどうにかしたいです。 詳しい方アドバイスお願いします。

  • SQLインジェクションの対策

    SQLインジェクションの対策 いつもお世話になっております。 SQLインジェクションの対策についてお伺いいたします。 もともと↓のようなSQL文だったものを "select user_id from table where user_id='{$user_id}'" 以下のように変更しました。 "select user_id from table where user_id='" . mysql_real_escape_string($user_id) . "'" 以下のように実行されていたSQL文は select user_idfrom table where user_id='10001' and 'a'='a' ↓のようにエスケープ処理して実行されるようになりました。(入力値は「10001' and 'a'='a」) select user_id from table where user_id='10001\' and \'a\'=\'a' ですが、phpMyAdminで実行してみるとどちらのSQL文も同じ結果が取得できてしまいます。 これでは対策になっていないと思ったので、質問させていただきました。 (magic_quotes_gpcはoffに設定しています。) なにか他の方法がいいのでしょうか。 ご教示よろしくお願いいたします。 <環境> PHP 5.1.6 MySQL 5.0.45

    • ベストアンサー
    • PHP

専門家に質問してみよう