ikepyonのだめ人間日記

セキュリティに関することを書いていく予定。

PHPアプリになぜ脆弱性が多いのか?

昨日、ざっくり数冊のPHP入門書を見たのだけど、がっくり来たorz
結構サンプルプログラムに脆弱性があったり、記述がだめだったりしているorz
こういうのがあるからダメなんだろうなぁと思った。
元々PHPは簡単という評判になっているので、プロのプログラマではない人が作っていることが多いと思う。その上「サンプルで学ぶPHP」みたいな本が大量に出回っているため、プログラムを書いたことのない人が、そのサンプルをコピペでプログラムを写しているのではないかと推測する。

加えてPHPのマニュアル自体にも問題があったり^^;

データベースへの問い合わせなどに際してクォートされるべき文字の前に バックスラッシュを挿入した文字列を返します。 クォートされるべき文字とは、シングルクォート('), ダブルクォート("),バックスラッシュ (\) ,NUL (NULL バイト) です。

addslashes() の使用例は、 データベースにデータを登録するときです。例えば、 O'reilly という名前をデータベースに挿入するには、 エスケープする必要があります。ほとんどのデータベースでは O\'reilly という具合に \ を使用します。これはデータベースにデータを格納する場合のみ必要です。 追加される \ は挿入されません。 PHP のディレクティブ magic_quotes_sybase を \ にすると、' はもうひとつの ' でエスケープされます。

PHP ディレクティブ magic_quotes_gpc はデフォルトでは on で、 全ての GET、POST、COOKIE データについて基本的に addslashes() を実行します。 magic_quotes_gpc によってすでにエスケープされた文字列に対して addslashes() を実行しないでください。 さもないと、重複してエスケープされてしまいます。 関数 get_magic_quotes_gpc() はこれを確認するのに役立つかも知れません。

http://php.chinaunix.net/manual/ja/function.addslashes.php

注)「\'」はSQLの規格ではエスケープではない。

データベースに渡される数値以外のユーザ入力を データベース固有の文字列エスケープ関数 (mysql_real_escape_string(), sql_escape_string(), など) でクオートしてください。 データベース固有の文字列エスケープ機能が利用できない場合、 addslashes() および str_replace()関数が利用できるでしょう。 (データベースの型に依存) 最初の例を参照 してください。前期の例が示すように、クエリの静的な部分をクオート するだけでは充分ではなく、簡単にクラックされてしまう可能性があ ります。

http://php.chinaunix.net/manual/ja/security.database.sql-injection.php

注)str_replaceは確かに利用できるだろうけど、addslashesは多くのDBでは意味がない

こんな感じでSQLエスケープを誤って理解しているように思える。
これらは、MySQL以外のDBでは誤った対策であるにもかかわらず、あたかも正しい対策のように書かれているのは問題であると思う。
今後、こういった過ちは直される方向のようだけど、なかなか浸透しないだろうなぁorz