| « gmailをgmail.comドメイン以外で使う! | IPv6でWormの脅威が軽減 » |
addslashesによるエスケープ処理は止めましょう
リンク: http://d.hatena.ne.jp/hoshikuzu/20060211#P20060211PHPSQLINJECTION
セキュリティmemoにaddslashesよるエスケープ処理でSQLインジェクションが可能なるという記事を見つけました。
私のセミナーを聞いたことがある方は「addslashesによるエスケープ処理は止めましょう」と言っていた事を覚えているでしょうか? mysql_real_escape_string()やpg_escape_string()等のデータベース専用のエスケープ関数を使いましょう、とも話しています。
ちなみにSQLiteを使っている場合はaddslashesでエスケープ処理はNGです。もっと根本的に間違っています。SQLiteではMS SQL Server, Sybaseと同様「'」は「''」とシングルクオートでエスケープします。
基本には忠実に :)
追記: サーバとクライアントのエンコーディングが合っていないと問題が発生します。PostgreSQLの場合、SET文でクライアントエンコーディングを変えるのではなくpg_set_client_encoding()を利用してエンコーディングを変えないとならないはずです。今は時間がないので後日また調べてまとめるようにします。
9 コメント
コメント from: komura [訪問者]
PostgreSQL でも、SET client_encoding TO 'SJIS'; を実行した後、"\x95' OR a = a; --" のような文字列を渡して、pg_escape_string() でエスケープすると、SQL インジェクションを引き起こすことが可能であることを確認しました(PostgreSQL 8.0.6/8.1.3)。
0x9527 という文字は本来は SJIS としては認められないはずですが、PostgreSQL では SJIS のマルチバイト文字として処理されるようです。
2006/02/15 @ 01:58
時間が無くて試していませんが、
SET client_encoding TO 'SJIS';
接続先のDBサーバにこのSQLを送信すると、クライアントのエンコーディングとサーバのエンコーディングが別のエンコーディングになるので基本的に間違っています。
要するにこうするとクライアントライブラリ(libpq)はサーバ側がSJISを使っている、ということを知らずに処理する事になります。
PostgreSQLサーバはSJISエンコーディングをサポートしていないのでクライアント側でクライアントエンコーディング->サーバエンコーディングに変換していた、と思います。(ここの記憶が怪しいですが、SETでインジェクションが可能になるならこうなっているはず。libpqの接続構造体がエンコーディングを保持していた記憶は確かなはず)
文字エンコーディングの違いでXSSが発生するのと同じで、SQLインジェクションできるようになるのは普通(?)の事だと思います。
# もしかして普通はそう考えない?
2006/02/15 @ 05:43
pg_set_client_encoding関数を使ってクライアントエンコーディングを設定すれば問題なく処理されるはずです。これが正しく処理されていないならPostgreSQLのセキュリティホール :)
専用の関数は単純なラッパーの場合もありますが、意味があって専用関数になっている場合もあります。内部仕様を完全に把握していない場合は専用関数を使うべきと思います。
2006/02/15 @ 05:46
とあるので、MySQLもmysql_real_escape_stringを使っていればどんな文字列で大丈夫なように作ってあると思います。仕様通りのエンコーディング指定をしていてもダメならMySQLのセキュリティホールという事に。
2006/02/15 @ 05:53
pg_set_client_encoding関数以外でエンコーディングを変えると問題になる事は知っていましたが(自分が実装した関数なので当たり前ですが)SETで変えるのと同じ、と思われている方もいるはずですね。非常に参考になりました。
時間が出来たらもう少し調べて確認してみたいと思います。
2006/02/15 @ 06:03
プリペアードクエリを使用すればエンコーディングが違っていても(本来これ自体問題なのですが)SQLインジェクションは出来ないはずですね。
エスケープ処理のミスのみでなく、エンコーディング設定のミスを防ぐためにもプリペアードクエリを使用した方が良いですね。
2006/02/15 @ 06:18
Iliaさんも同じ事を書いているのですね。と思ったら、リンク先のブログにもリンクあるし。よく読まないといかんですね。
2006/02/15 @ 06:29
コメント from: komura [訪問者]
結果としては、
SET client_encoding TO 'SJIS';
を実行してから SQL を実行したのと同様の結果になりました(0x9527 が SJIS の文字として見なされ、SQL インジェクション可能)。
PHP 5.1.2 と PostgreSQL 8.1.3 で確認しました。
あと、ご指摘通り、pg_prepare() と pg_execute() によるプリペアードクエリでは問題ありませんでした(文字コードが SJIS の場合でも SQL インジェクションを起こせない)。
PHP 側でこれらの関数が導入されたのは PHP 5.1.0 以降のようですので、それより前のバージョンでは文字コードに SJIS を使用しないようにするしかないように思います。
2006/02/18 @ 10:17
コメント from: 石井 [訪問者]
2006/02/19 @ 23:44