PDOにおけるSQLインジェクションの危険性とその回避についてまとめ
- yousukezan
- 9271
- 0
- 19
- 0
日記書いた『ぼくがPDOを採用しなかったわけ(Shift_JISによるSQLインジェクション) 』 http://www.tokumaru.org/d/20100701.html#p01
2010-07-01 09:25:42@ockeghemさんの日記を見てふと思い出したがMySQLのJDBC大丈夫だっけ?\の取り扱いを妙な対応してたよなぁ
2010-07-01 10:01:23PDO::MYSQL_ATTR_DIRECT_QUERY を false RT: @ockeghem: 日記書いた『ぼくがPDOを採用しなかったわけ(Shift_JISによるSQLインジェクション) 』 http://bit.ly/aAKdEL
2010-07-01 10:37:59PDO::ATTR_EMULATE_PREPARESをfalseにすると、よさそうです RT @haruyama: PDO::ATTR_EMULATE_PREPARES も falseにしておく必要があるか
2010-07-01 10:50:32.@ockeghem 「PDOは接続時に文字エンコーディングを指定できない(指定しても無視される)」ってほんとうですか? mysql_real_connect() が my.cnfの [client]セクションを読むので, my.cnfを指定することで可能と認識していましたが.
2010-07-01 10:51:31PDO、小泉守義さんのブログによると、昔は名前つきプレイスホルダ使用時にエミュレーションしてたけど、今は、PDO::ATTR_EMULATE_PREPARESをfalseにすると、名前つきプレイスホルダでも、プリペアード・ステートメントになるようですね
2010-07-01 10:52:48パケットキャプチャする限りは、常にLatin1ですね。私がWindows上で試しているから、という可能性はあります。 RT @haruyama: .@ockeghem 「PDOは接続時に文字エンコーディングを指定できない(指定しても無視される)」ってほんとうですか?
2010-07-01 10:56:59.@haruyama ありがとうございます。問題はそこではなくて、PDOがPrepared Statuementのエミュレーションする時のパーサが文字エンコーディングを考慮するかどうかなんですね
2010-07-01 11:01:20@ockeghem 試してないですけれど、http://bit.ly/awE8ZR を読む限りではDBD::mysqlと同じようにREAD_DEFAULT_FILEを指定することによってcharset指定できるんじゃないすかね
2010-07-01 11:02:46.@ockeghem Cのmysql_real_escape_string()の第1引数に関係しています. PHPソースのmysql_handle_quoter() の中ですね
2010-07-01 11:05:09@ockeghem あ、libmysqlclientの動的プレースホルダじゃなくてPDOが独自にやってるのであれば結局意味ないのかな、、試してみるかな
2010-07-01 11:05:18.@ockeghem MySQLの中まではみてないのですが, 適当に[client]で文字セットが設定されていたり サーバが文字セットを強制していれば 適当な文字エンコーディングでのエスケープが行なわれると思うのですが
2010-07-01 11:06:53.@haruyama PDOがmysql_real_escape_string()を呼んでいるかどうかが問題になると思います。少し古いですが、https://www.codeblog.org/blog/moriyoshi/20061221.html
2010-07-01 11:09:17Windowsでは、PDO::MYSQL_ATTR_READ_DEFAULT_FILEが無効で、my.cnfが指定できないようです。Linux上で調べます RT @haruyama: …my.cnf で指定してもだめですか?
2010-07-01 11:20:10.@ockeghem pdoのSQLのパースがこのままなら Shift_JISの場合は書いてあるようにおかしくなりますね.
2010-07-01 11:21:53.@ockeghem pdo_sql_parser.re からは stmt->dbh->methods->quoter という形で mysql_handle_quoter()が呼ばれています(MySQLなら)
2010-07-01 11:23:23.@haruyama 遅ればせながらPDOのソースを見たら、mysql_real_escape_string()を呼んでいるようでもあるので、もう少し調べます
2010-07-01 11:23:32@ockeghem どんな問題について話しているのか追えてないので的はずれなことをいってそうですが、mysql_real_escape_string() は、PDO の MySQL ドライバが入った当初から使われていました。
2010-07-01 11:26:21これです http://www.tokumaru.org/d/20100701.html#p01 RT @moriyoshit: @ockeghem どんな問題について話しているのか追えてない…
2010-07-01 11:29:09@ockeghem 文字エンコーディングが考慮されないのは、MySQL の実装が古いなどの理由で、プリペアードステートメントが PDO 側でエミュレーションされる場合です。
2010-07-01 11:30:01@ockeghem その場合、SQL が一旦 PDO でパースされ、プレースホルダが抽出されるのですが、このパーサが文字エンコーディングを考慮していません。
2010-07-01 11:30:10.@moriyoshit なるほど。すると、パーサが通った後のエスケープでは、文字エンコーディングを考慮しているということでしょうか?
2010-07-01 11:32:20@ockeghem PHP 5.3.0 とリンクしている libmysqlclient のバージョンが古い可能性があります。 niMySQL は positional な placeholder をサポートしているので、この部分がなんちゃって、になることはありません。
2010-07-01 11:39:10