« gmailをgmail.comドメイン以外で使う!IPv6でWormの脅威が軽減 »

9 comments

Comment from: komura [Visitor]
リンク先ではデータベース側で文字列を SJIS として処理している場合は、mysql_real_escape_string() や pg_escape_string() 等のデータベース専用のエスケープ関数を使用してもエスケープ処理が回避されてしまうことが書かれています。
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
Comment from: Yasuo Ohgaki [Member] Email · http://www.ohgaki.net/
なるほど。文字エンコーディングの違い問題が発生する典型的な例ですね。

時間が無くて試していませんが、

SET client_encoding TO 'SJIS';

接続先のDBサーバにこのSQLを送信すると、クライアントのエンコーディングとサーバのエンコーディングが別のエンコーディングになるので基本的に間違っています。

要するにこうするとクライアントライブラリ(libpq)はサーバ側がSJISを使っている、ということを知らずに処理する事になります。

PostgreSQLサーバはSJISエンコーディングをサポートしていないのでクライアント側でクライアントエンコーディング->サーバエンコーディングに変換していた、と思います。(ここの記憶が怪しいですが、SETでインジェクションが可能になるならこうなっているはず。libpqの接続構造体がエンコーディングを保持していた記憶は確かなはず)

文字エンコーディングの違いでXSSが発生するのと同じで、SQLインジェクションできるようになるのは普通(?)の事だと思います。
# もしかして普通はそう考えない?

2006/02/15 @ 05:43
Comment from: Yasuo Ohgaki [Member] Email · http://www.ohgaki.net/
正しい設定方法を書いていなかったですね。

pg_set_client_encoding関数を使ってクライアントエンコーディングを設定すれば問題なく処理されるはずです。これが正しく処理されていないならPostgreSQLのセキュリティホール :)

専用の関数は単純なラッパーの場合もありますが、意味があって専用関数になっている場合もあります。内部仕様を完全に把握していない場合は専用関数を使うべきと思います。
2006/02/15 @ 05:46
Comment from: Yasuo Ohgaki [Member] Email · http://www.ohgaki.net/
mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a.

とあるので、MySQLもmysql_real_escape_stringを使っていればどんな文字列で大丈夫なように作ってあると思います。仕様通りのエンコーディング指定をしていてもダメならMySQLのセキュリティホールという事に。
2006/02/15 @ 05:53
Comment from: Yasuo Ohgaki [Member] Email · http://www.ohgaki.net/
今日のところはちょっと時間不足なので、最後にkomuraさんコメントありがとうございます。

pg_set_client_encoding関数以外でエンコーディングを変えると問題になる事は知っていましたが(自分が実装した関数なので当たり前ですが)SETで変えるのと同じ、と思われている方もいるはずですね。非常に参考になりました。

時間が出来たらもう少し調べて確認してみたいと思います。
2006/02/15 @ 06:03
Comment from: Yasuo Ohgaki [Member] Email · http://www.ohgaki.net/
もう一つ対処方法を。

プリペアードクエリを使用すればエンコーディングが違っていても(本来これ自体問題なのですが)SQLインジェクションは出来ないはずですね。

エスケープ処理のミスのみでなく、エンコーディング設定のミスを防ぐためにもプリペアードクエリを使用した方が良いですね。
2006/02/15 @ 06:18
Comment from: Yasuo Ohgaki [Member] Email · http://www.ohgaki.net/
http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared-Statements.html

Iliaさんも同じ事を書いているのですね。と思ったら、リンク先のブログにもリンクあるし。よく読まないといかんですね。
2006/02/15 @ 06:29
Comment from: komura [Visitor]
遅くなってしまいましたが、pg_set_client_encoding( 'SJIS' ) を実行してから同様の事を検証してみました。

結果としては、

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
Comment from: 石井 [Visitor]
pg_set_client_encodingを呼ぶのと,SET client_encoding TO をするのは,PostgreSQL 7.4以降であれば同じです.違っていたのは7.3以前の話ですね.
2006/02/19 @ 23:44

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
PoorExcellent
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)