用語辞典
SQLインジェクション(SQLi)とは — 入力でデータベースの命令を書き換えられる穴
SQLインジェクション(SQLi)は、利用者の入力がデータベースへの命令(SQL)の意味を書き換えてしまう脆弱性です。データの読み出し・改ざん・全削除につながります。仕組みの図解と、本命の防御(プレースホルダ=プリペアドステートメント、ORM、最小権限DB)を、攻撃手順を伏せて防御目線で解説します。
「検索ボックスに入れた文字が、データベースへの“命令の一部”になってしまう」——それがSQLインジェクションです。仕組みと確実な防ぎ方を解説します(攻撃手順は載せません)。
なぜ起きるのか(仕組み)
危険の根っこは、SQL文を文字列連結で組み立てることです。「入力を文章にそのまま混ぜる」と、入力が“値”の境界を越えて“命令”として効いてしまいます。
✗ 文字列連結(危険)
入力を文章に直接連結 → 入力が命令の一部として解釈されうる
✓ プレースホルダ(安全)
値は ? / $1 等の枠に“データ”として渡す → 常に値のまま
被害は「そのDB接続でできること」全部です。内部DBに到達できれば、RCE や SSRF と並ぶ、大規模漏えいの典型的な入口になります。
防御
プレースホルダ(プリペアドステートメント)を使う(最重要)
SQLの組み立てに文字列連結を使わない。値は ? / 名前付きパラメータ等で“データ”として渡す。これだけでこの脆弱性のクラスがほぼ消える。
ORM/クエリビルダに任せる
多くのORMは既定でプレースホルダを使う。自前の生SQLを書く場面を減らすほど安全。生SQLが必要でも必ずパラメータ化する。
DBユーザーを最小権限に
アプリ用のDBユーザーに不要な権限(DROP・他テーブル・管理操作)を与えない。万一突破されても被害を縮める。
入力の検証は“補助”として
型・長さ・形式の検証は有効だが、これ単体を防御の本命にしない。あくまでプレースホルダの上乗せ。
ITDの視点:そもそも“生SQLを手で組む”をやめる
SQLiは長く存在するのに無くならない——理由は「便利だから入力を文章に混ぜてしまう」からです。ITDの立場は明快で、値を文字列連結でSQLに入れる場面を作らないこと。プレースホルダかORMを既定にすれば、この脆弱性は設計段階で構造的に消えます。手動エスケープで頑張る方向には行かないでください。
盲点:プレースホルダで“値”しか渡せない
プレースホルダは万能ではありません。渡せるのは 値 だけで、テーブル名・カラム名・ORDER BY の方向(昇順/降順) といった“クエリの構造”には使えません。
ここを動的にしたいとき(例:「並び替えキー」「絞り込み列」をユーザーに選ばせる)は、入力をそのままSQLに入れず、あらかじめ決めた許可リストから対応する正規の名前を選ぶ形にします。「ソート列」「フィルタ列」は、プレースホルダで守れていると油断しがちな典型的な盲点です。
次に読む
よくある質問
QSQLインジェクションで何が起きる?
攻撃者がデータベースへの問い合わせの意味を変え、本来見えないデータの読み出し、データの改ざん、最悪は全件削除や認証の回避までできてしまいます。個人情報の大量流出の典型的な原因の一つです。
Q一番確実な防御は?
『プレースホルダ(プリペアドステートメント)で値を渡す』ことです。SQL文の組み立てに文字列連結を使わず、値はあくまで“データ”として別経路で渡します。これで入力が命令として解釈される余地がなくなります。多くのORMは既定でこれを行います。
Q入力をエスケープすれば十分?
手動エスケープは抜けが出やすく非推奨です。本命はプレースホルダ。加えてDBユーザーを最小権限にし、万一を想定して被害範囲を縮めます。