SQLインジェンクション対策に有効なプリアドステートメントですが、よく分かっていなかった「静的」、「動的」の意味と、エミュレートの設定について、今後迷うことがないよう、まとめてみました。
先に結論から書くと脆弱性を無くすには、「エミュレートは使わない」、プレースホルダは、「静的」にする、が正解です。
プレースホルダ
- 「本物」 (静的プレースホルダ)
- 「偽物(エミュレーション)」 (動的プレースホルダ)
- プリペアドらしい記述を文字列結合してSQLを構築する
- 文字コードの違いや不正文字によるエスケープ抜けは起こりうる
PHP + MySQL では動的プレースがデフォルトなので、パラメータを変更する必要があります。
PHP + Postgres は…? 分からない時は、設定しましょう。
こんな感じですね。 $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
PDO::ATTR_EMULATE_PREPARES
PDO::ATTR_EMULATE_PREPARES の true/false でどうなるかをまとめました。
まずこれは、「プリペアドステートメント」のエミュレーションを有効または無効にするものです。
- true
- 常にプリペアドステートメントをエミュレート(パフォーマンスはあがるので、あえて true にするアプリもある…)
- false
- ネイティブのステートメントを使う
- SQLが正しく準備できなければ、エミューレートを使う(※1)
PHP の「プリペアドステートメント」のエミュレーション・モードのデフォルト状態
- 5.1 false
- 5.2 true
- 5.6 ?
PDO を使うときは、明示的に「PDO::ATTR_EMULATE_PREPARES を false にする」が正解です。
が、※1 のように、SQLに何かしら不備があれば、エミュレートモードになってしまう…。これは怖い。
デバッグツールなど使って、実行時のSQLを確認することの大切さが分かりました。
PHP ではデフォルト値が最近は true になっているのかも。
また時間があれば、更新します。