SQLのバインド機構は、SQLの構造と、条件などに使う値を分離して扱う仕組みです。プリペアドステートメントやパラメーター化クエリを適切に使うことで、SQLインジェクションへの対策になります。文字列を連結してSQLを作る方法との違いを押さえましょう。
プレースホルダーへ値を渡す
SELECT name FROM users WHERE user_id = ?;
これは学習用のSQL例です。?の位置へ、SQLのコードではなく検索値をパラメーターとして渡します。実際の記号は、データベースやライブラリにより?、$1、:idなどが使われます。
- 値の部分をプレースホルダーにしたSQLを用意する。
- ライブラリのパラメーター機能で値を渡す。
- SQLの命令と値を区別した形で実行する。
文字列連結との違い
| 方法 | 入力の扱い |
|---|---|
| SQL文字列へ入力値を直接連結 | 入力に含まれる記号などがSQLの構造に影響する危険がある |
| パラメーターとして渡す | 値をSQLの命令から分離して処理する |
クォートで囲むだけ、入力中の一部の記号を削除するだけの対策とは異なります。SQLを組み立てた後に文字列を単に置換することを、正しいパラメーター化と混同しないことも大切です。
何でもバインドできるわけではない
通常の値パラメーターは、テーブル名、列名、ASC/DESCなどSQLの構造を自由に置き換える用途には使えません。構造を切り替える必要がある場合は、許可した固定候補との対応付けなどで制御します。
一部だけパラメーター化しても、別の入力をSQL文字列へ連結すれば危険が残ります。ORMやストアドプロシージャを使っていても、内部で動的SQLを不適切に組み立てれば同様です。
性能と他の対策
実行計画の再利用などで効率が上がる場合がありますが、DBMS・ライブラリ・SQL・実行条件に左右され、常に高速になるとは限りません。入力の型や範囲の検証、DBの最小権限、適切なエラー処理も併せて考えます。
確認問題:列名も、値と同じプレースホルダーへ自由に渡せる?
通常の値パラメーターではできません。列名などのSQL構造は、許可した候補との対応付けなどで安全に制御します。
noteで関連用語と対策を整理
情報セキュリティのnote教材でSQLインジェクションの狙いと対策を復習しましょう。「入力を削る」ではなく「命令とデータを分ける」理由を説明できると、選択肢を見分けやすくなります。


コメント