FlawOpen

flawopen.com/SQL Injection/パラメータ化クエリとは?

かんたんに言うと、パラメータ化クエリとは?

リファレンスページ
かんたんに言うと

ラベル付きの空欄がある用紙を考えてください。プログラムは指示を固定したまま、データベースライブラリに各値を対応する欄へ入れるよう頼みます。ライブラリはサーバー側のネイティブな準備を使う場合も、クライアント側でエミュレートする場合もありますが、アプリのコードでユーザー入力を指示文に書き加えてはいけません。

仕組み

サーバー側でネイティブに準備する場合、ドライバはプレースホルダを含む SQL を準備し、実行時に束縛値を渡します。プロトコルやタイミングはデータベースとドライバによって異なります。準備処理をクライアント側でエミュレートするドライバもあり、PDO はこのモードを明記しています。そのため API 呼び出しだけでは値の転送方法は分かりません。SQL 構造を固定し、ドライバの仕様に沿った束縛 API を使い、ネイティブとエミュレートのどちらが有効か確認してください。

これが単に「丁寧にエスケープする」のと違う理由

手動エスケープでは、連結する前にアプリのコードで値を正しくエンコードする必要があり、脆弱で文脈にも左右されます。パラメーター束縛 API は値の処理をドライバに任せます。サーバー側のネイティブ準備では値はプロトコル上の別パラメーターとして送られ、エミュレートではドライバがクライアント側でプレースホルダを処理します。アプリが組み立てる SQL 文字列にユーザー入力を入れず、ドライバが文書化する束縛動作を確認してください。

FAQ

これは「プリペアドステートメント」と同じもの?

密接に関連します。プリペアドステートメントは固定されたクエリ構造からデータベース側に作られるオブジェクトで、パラメータ化はそれに値を別途束縛する手法です。両者はしばしば同じ意味で使われます。

これはクエリのあらゆる部分に使えますか?

値(データ)にのみ有効で、テーブル名や列名のような識別子には使えません。それらには別の防御、通常は許可リストが必要です。

参考文献

関連項目 SQL インジェクション(CWE-89)の仕組みと各言語での防ぎ方 — flawopen.com Prisma $queryRaw は SQL Injection に安全? Railsのwhere()文字列補間は安全? Sequelize query() は SQL Injection に安全? SQLAlchemy text() は SQL Injection に安全? sqlx のコンパイル時クエリ検査は SQL インジェクションを防ぎますか? ストアドプロシージャは SQL インジェクションを防ぎますか?