$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をエスケープしています。
よろしくお願いいたします。
選択結果が異なります。
$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に脆弱性があったり、新しいインジェクションが発見されたりした場合、即座に対応できませんので。
mysql_real_escape_string 関数だけで既知の SQL インジェクションに対応できるかというと、そうではありません。
有名な例としては、マルチバイトコード問題があります。
もし内部コードをシフトJISで処理しているとすると、$name = ""\x97' or 1=1" を mysql_real_escape_string 関数 に通すと、"予' or 1=1" となってしまいます。シングルクォーテーションがエスケープされないのです。
結果的に、SQL文がエラーを起こすか、場合によってはインジェクションされる可能性があります。
もっとも、これは SQLインジェクションの問題ではなく、マルチバイトコードに対する設計の甘さから起きる問題です。
SQLインジェクション対策に加え、マルチバイトコード対策、入力値バリデーションチェックをきちんと行っていれば、DBへの攻撃は避けられるでしょう。
SQLインジェクション対策という意味では、mysql_real_escape_string() を用いることでSQLの特殊文字がエスケープされるので、いずれにしても安全である、ということになります。
Pear::DBのプリペアドステートメントなんかでも、MySQLドライバのコードを追えば分かりますが、結局 execute → executeEmulateQuery → quoteSmart → escapeSimple → mysql_real_escape_string と呼び出していますので、同じですね。
なるほど、参考になります。
なるほど。参考になります。
ところで私は
$sql = sprintf("SELECT * FROM `hatenainfo` WHERE name = '%s'", mysql_real_escape_string($name));
の方法を使用しいているのですが、現在知られているSQLインジェクションには問題なく対応できているのでしょうか?