PHP & SQL Injection対策


$sql = sprintf("SELECT * FROM `hatenainfo` WHERE name = '%s'", mysql_real_escape_string($name));

$sql = "SELECT * FROM `hatenainfo` WHERE name = 'mysql_real_escape_string($name)'";

は何が異なるのでしょうか?
どちらの方が安全ですか?

また、Pear DBやAdodbを使用する際、単に

$db->EXECUTE("SELECT * FROM `hatenainfo` WHERE name = ?", array($_POST['name']));
とやっても安全でしょうか?

*今回はSQLインジェクションのみお願いいたします。表示する際は問題なくHTMLをエスケープしています。

よろしくお願いいたします。

回答の条件
  • 1人3回まで
  • 登録:
  • 終了:2009/02/02 09:45:02
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:pahoo No.1

回答回数5960ベストアンサー獲得回数633

ポイント27pt

選択結果が異なります。

$sql = sprintf("SELECT * FROM `hatenainfo` WHERE name = '%s'", mysql_real_escape_string($name));

テーブル hatenainfo の中から、カラム name と変数 $name を mysql_real_escape_string でエスケープした結果が合致するレコードを選択します。

$sql = "SELECT * FROM `hatenainfo` WHERE name = 'mysql_real_escape_string($name)'";

テーブル hatenainfo の中から、カラム name と文字列 'mysql_real_escape_string($name)' が合致するレコードを選択します。


ご質問の SQL 文は勘違いだと思うのですが、PHP の mysql_real_escape_string は MySQL の C API "mysql_real_escape_string" をインターフェースするだけなので、PHP 側でエスケープしても、MySQL 側でエスケープしても結果は同じです。

ただし、PHPに限らない一般論として、アプリケーション側(言語側)で DBMS が用意するエスケープ手段を適用するのが定石となっています。


単に

$db->EXECUTE("SELECT * FROM `hatenainfo` WHERE name = ?", array($_POST['name']));

とやっても安全でしょうか?

いちおう安全ということになっています。

ただ、個人的には、自力でSQLインジェクション対策のコードを書いた方が良いと考えています。Pead::DBに脆弱性があったり、新しいインジェクションが発見されたりした場合、即座に対応できませんので。

id:esecua

なるほど。参考になります。

ところで私は

$sql = sprintf("SELECT * FROM `hatenainfo` WHERE name = '%s'", mysql_real_escape_string($name));

の方法を使用しいているのですが、現在知られているSQLインジェクションには問題なく対応できているのでしょうか?

2009/01/26 15:20:20
id:pahoo No.2

回答回数5960ベストアンサー獲得回数633

ポイント27pt

mysql_real_escape_string 関数だけで既知の SQL インジェクションに対応できるかというと、そうではありません。


有名な例としては、マルチバイトコード問題があります。

もし内部コードをシフトJISで処理しているとすると、$name = ""\x97' or 1=1" を mysql_real_escape_string 関数 に通すと、"予' or 1=1" となってしまいます。シングルクォーテーションがエスケープされないのです。

結果的に、SQL文がエラーを起こすか、場合によってはインジェクションされる可能性があります。


もっとも、これは SQLインジェクションの問題ではなく、マルチバイトコードに対する設計の甘さから起きる問題です。

SQLインジェクション対策に加え、マルチバイトコード対策、入力値バリデーションチェックをきちんと行っていれば、DBへの攻撃は避けられるでしょう。


参考サイト

id:sphire No.3

回答回数115ベストアンサー獲得回数12

ポイント26pt

SQLインジェクション対策という意味では、mysql_real_escape_string() を用いることでSQLの特殊文字がエスケープされるので、いずれにしても安全である、ということになります。

Pear::DBのプリペアドステートメントなんかでも、MySQLドライバのコードを追えば分かりますが、結局 execute → executeEmulateQuery → quoteSmart → escapeSimple → mysql_real_escape_string と呼び出していますので、同じですね。

id:esecua

なるほど、参考になります。

2009/01/27 02:14:04

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません