SQLインジェクション(SQLi)とは:入力でデータベースへの命令を書き換えられる脆弱性
SQLインジェクション(SQLi)は、利用者の入力がデータベースへの命令(SQL)の意味を書き換えてしまう脆弱性です。データの読み出し・改ざん・全削除につながります。仕組みの図解と、基本の防御(プレースホルダ=プリペアドステートメント、ORM、最小権限DB)を、攻撃手順を伏せて防御目線で解説します。
- 公開日
- 更新日
SQLインジェクションは、検索ボックスなどに入れた文字が、データベースへの“命令の一部”になってしまう脆弱性です。仕組みと確実な防ぎ方を解説します(攻撃手順は載せません)。
なぜ起きるのか(仕組み)
危険の原因は、SQL文を文字列連結で組み立てることです。「入力を文章にそのまま混ぜる」と、入力が“値”の境界を越えて“命令”として効いてしまいます。
✗ 文字列連結(危険)
入力を文章に直接連結 → 入力が命令の一部として解釈されうる
✓ プレースホルダ(安全)
値は ? / $1 等の枠に“データ”として渡す → 常に値のまま
被害は「そのDB接続でできること」全部です。内部DBに到達できれば、RCE や SSRF と並ぶ、大規模漏えいの典型的な原因になります。
防御
プレースホルダ(プリペアドステートメント)を使う(最重要)
SQLの組み立てに文字列連結を使わない。値は ? / 名前付きパラメータ等で“データ”として渡す。これだけでこの脆弱性のクラスがほぼ消える。
ORM/クエリビルダに任せる
多くのORMは既定でプレースホルダを使う。自前の生SQLを書く場面を減らすほど安全。生SQLが必要でも必ずパラメータ化する。
DBユーザーを最小権限に
アプリ用のDBユーザーに不要な権限(DROP・他テーブル・管理操作)を与えない。万一突破されても被害を縮める。
入力の検証は“補助”として
型・長さ・形式の検証は有効だが、これ単体を防御の中心にしない。あくまでプレースホルダの上乗せ。
当サイトの視点:そもそも“生SQLを手で組む”をやめる
SQLiは長く知られているのに無くなりません。理由は「便利だから入力を文章に混ぜてしまう」からです。当サイトの立場は明快で、値を文字列連結でSQLに入れる場面を作らないこと。プレースホルダかORMを既定にすれば、この脆弱性は設計段階で構造的に消えます。手動エスケープで頑張る方向には行かないでください。
注意点:プレースホルダで渡せるのは値だけ
プレースホルダは万能ではありません。渡せるのは値だけで、テーブル名・カラム名・ORDER BY の方向(昇順/降順) といった“クエリの構造”には使えません。
ここを動的にしたいとき(例:「並び替えキー」「絞り込み列」をユーザーに選ばせる)は、入力をそのままSQLに入れず、あらかじめ決めた許可リストから対応する正規の名前を選ぶ形にします。「ソート列」「フィルタ列」は、プレースホルダで守れていると油断しがちな典型的な盲点です。
入力は画面のフォームだけではない
「検索ボックスやログインフォームだけ気をつければよい」と考えると、漏れが出ます。SQLに入る可能性がある値は、次のようにいくつもの経路から届きます。
- HTTPヘッダ(
User-Agent・X-Forwarded-Forなど)やCookie - APIで受け取るJSONの値や、ファイルから読み込んだ値
- 一度データベースに保存され、後で別の処理がSQLに組み込む値
最後の例は「二次的なSQLインジェクション」と呼ばれます。保存するときはプレースホルダを使っていても、取り出した値を別の処理で文字列連結すると成立します。「自分のDBから読んだ値だから安全」とは考えず、どこでSQLを組み立てる場合もプレースホルダを使います。
当サイトの解説 X-Forwarded-For の偽装 では、ヘッダに仕込まれた探索用の文字列が届いても、値をプレースホルダで渡していたためSQLインジェクションが成立しなかった例を紹介しています。
似た用語との違い
「インジェクション」と名の付く脆弱性は、入力が別の言語の命令として解釈される点で共通しています。違いは、入力が混ざる先です。
| 用語 | 入力が混ざる先 | 主な被害 | 根本の対策 |
|---|---|---|---|
| SQLインジェクション | データベースへの命令(SQL) | データの読み出し・改ざん・削除 | プレースホルダ |
| XSS | 利用者のブラウザで動くHTMLやJavaScript | 利用者のセッションの悪用、画面の偽装 | 出力時のエスケープとCSP |
| OSコマンドインジェクション | サーバーのシェルが実行するコマンド | サーバー上での任意のコマンド実行(RCE) | シェルを経由しないAPIを使い、引数を分けて渡す |
SQLインジェクションとXSSはよく並べて語られますが、被害を受ける場所が違います。SQLインジェクションはサーバー側のデータベース、XSSは利用者のブラウザです。
主な言語でのプレースホルダの呼び方
どの主要な言語にも、値を別に渡す仕組みが用意されています。自分の使っている環境で、どの機能を使えばよいかの目安にしてください。
| 言語・ライブラリ | 使う機能 |
|---|---|
| Java(JDBC) | PreparedStatement と setString などの値の設定 |
| PHP(PDO) | prepare で文を準備し、execute に値を渡す |
| Python(DB-API) | execute の第2引数に値を渡す(SQL文に値を埋め込まない) |
| Node.js(pg など) | $1 のような番号付きの記号と、値の配列を別に渡す |
| C#(.NET) | コマンドの Parameters に値を追加する |
どの言語でも、SQL文を作るときにテンプレート文字列や + で値を埋め込んだ時点で、この仕組みは効かなくなります。
具体例:製品のSQLインジェクションから始まった大規模漏えい
SQLインジェクションは古くから知られた脆弱性ですが、今も大きな漏えいの原因になっています。最近の例は、自分で書いたコードではなく、使っている製品の脆弱性から始まったものが目立ちます。
| 事例 | 何が起きたか |
|---|---|
| MOVEit Transfer(2023年) | ファイル転送製品のSQLインジェクション(CVE-2023-34362)が修正前に悪用され、委託先を通じて2,700を超える組織のデータが持ち出された(→ MOVEit 大規模情報漏えい) |
| Metabase(2026年) | 分析ツールの認証なしSQLインジェクション(CVE-2026-72898)が修正前から悪用され、複数の企業が顧客情報の流出を公表した(→ Metabaseの悪用と流出) |
| WordPress本体(2026年) | 別の脆弱性と組み合わせると、認証なしのSQLインジェクションからRCEに至り得る(→ CVE-2026-63030の解説) |
MOVEitの事案を受けて、米国のCISAとFBIは2024年3月、SQLインジェクションを製品から根絶するよう求める注意喚起を出し、対策としてプレースホルダ(パラメータ化したクエリ)を挙げました。MITREが2025年12月に公表した「CWE Top 25」でも、SQLインジェクション(CWE-89)は2位です。
立場によって、やることが違う
| あなたの立場 | 最初にやること |
|---|---|
| 自分でSQLを書く(開発者) | 文字列連結をやめてプレースホルダかORMにする。生SQL用の関数の使い方を見直す |
| 製品やOSSを使う(運用者) | 使っている製品のCVEとKEVを確認し、修正版へ更新する。外から到達できる管理画面を減らす |
| 両方に共通 | アプリ用のDBユーザーを最小権限にし、読めるテーブルと列を必要な範囲に絞る |
自分の環境で確認する方法
攻撃用の文字列を入力して試す必要はありません。コードと設定で確かめられます。
SQLを文字列で組み立てている箇所を探す
ソースコードを、SQLの命令語(SELECT・WHERE など)と文字列連結やテンプレート文字列が同じ行にある箇所で検索する。生SQL用の関数($queryRawUnsafe・whereRaw・DB::raw・raw() など)に入力が連結されていないかも確認する。
DBユーザーの権限を書き出す
アプリが使うDBユーザーが、どのテーブルに何をできるかを確認する(MySQLなら SHOW GRANTS、PostgreSQLなら information_schema.role_table_grants)。不要な削除権限や、他のアプリのテーブルへの権限があれば外す。
使っている製品を脆弱性情報と照合する
CVE / KEV ルックアップで、使っている製品の脆弱性と、実際に悪用中かを確認する。依存ライブラリは osv-scanner で一括確認できる。
SQLのエラーを画面に出していないか
本番環境で、データベースのエラーメッセージがそのまま利用者に表示されていないかを確認する。詳しいエラーはログにだけ残す。
ログで兆候を見る
データベースの構文エラーが急に増えていないか、WAFやアクセスログに同じ相手からのSQLらしい文字列を含むリクエストが続いていないかを確認する。兆候があれば、その経路のコードを優先して見直す。
出典(一次情報)
- OWASP「SQL Injection Prevention Cheat Sheet」 — cheatsheetseries.owasp.org(プレースホルダ、ストアドプロシージャの注意点、許可リストによる入力の検証、最小権限、エスケープを主な対策にしないこと)
- CISA・FBI「Secure by Design Alert: Eliminating SQL Injection Vulnerabilities in Software」(2024年3月25日) — cisa.gov
- MITRE「2025 CWE Top 25 Most Dangerous Software Weaknesses」(2025年12月) — cwe.mitre.org(CWE-89 が2位)
- IPA「安全なウェブサイトの作り方」 — ipa.go.jp(根本的解決と保険的対策)
次に読む
- 用語:RCE とは / XSS とは / OWASP Top 10 とは
- 解説:X-Forwarded-For の偽装と信頼するプロキシの設定
- 入門:セキュリティ超入門
分類番号
CWE は脆弱性の原因となる弱点の種類を、MITRE ATT&CK は攻撃者の手口を分類した番号体系です。どちらも MITRE が管理し、脆弱性情報や検知ルールの分類に広く使われています。
CWE(弱点の種類)
ATT&CK(攻撃の手口)
CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use
© 2026 The MITRE Corporation. This work is reproduced and distributed with the permission of The MITRE Corporation. MITRE ATT&CK and ATT&CK are registered trademarks of The MITRE Corporation. The MITRE Corporation (MITRE) hereby grants you a non-exclusive, royalty-free license to use ATT&CK® for research, development, and commercial purposes. Any copy you make for such purposes is authorized provided that you reproduce MITRE's copyright designation and this license in any such copy. ATT&CK Terms of Use
よくある質問
QSQLインジェクションで何が起きる?
攻撃者がデータベースへの問い合わせの意味を変え、本来見えないデータの読み出し、データの改ざん、最悪は全件削除や認証の回避までできてしまいます。個人情報の大量流出の典型的な原因の一つです。
Q一番確実な防御は?
『プレースホルダ(プリペアドステートメント)で値を渡す』ことです。SQL文の組み立てに文字列連結を使わず、値はあくまで“データ”として別経路で渡します。これで入力が命令として解釈される余地がなくなります。多くのORMは既定でこれを行います。
Q入力をエスケープすれば十分?
手動エスケープは漏れが出やすく非推奨です。基本はプレースホルダ。加えてDBユーザーを最小権限にし、万一を想定して被害範囲を縮めます。
QORMを使っていれば安全?
通常の使い方なら安全です。ORMは既定で値をプレースホルダとして渡します。ただし、生のSQLを書くための関数(Prismaの $queryRawUnsafe、Laravelの whereRaw・DB::raw、Djangoの raw や extra など)に入力を文字列で連結すると、ORMを使っていても同じ脆弱性が生まれます。並び替えの列名など、プレースホルダで渡せない部分も要注意です。
QWAFを入れればSQLインジェクションは防げる?
被害を減らす助けにはなりますが、根本の対策にはなりません。IPAの「安全なウェブサイトの作り方」も、根本的な解決(プレースホルダ)と、被害を減らす保険的な対策を分けて示しています。WAFは後者で、検知をすり抜ける入力もあります。コードを直すまでのつなぎとして使います。
Q自分が使っている製品にSQLインジェクションがあるかはどう知る?
製品名とバージョンで、公開済みの脆弱性(CVE)と、実際に悪用が確認された脆弱性の一覧(CISAのKEV)を照合します。当サイトの CVE / KEV ルックアップでも調べられます。MOVEit Transfer や Metabase のように、使っている製品側のSQLインジェクションが大規模な漏えいにつながった例は少なくありません。
Qプリペアドステートメントとは?
SQL文の形(どこに値が入るか)を先にデータベースへ渡し、値は後から別に渡す仕組みです。値を入れる場所は ? や $1 のような記号(プレースホルダ)で示します。文の形が先に決まっているため、後から渡す値がどんな文字でも、命令として解釈されることはありません。
QブラインドSQLインジェクションとは?
データベースの中身やエラーが画面に表示されない場合でも、応答の違いや応答時間の差から情報を少しずつ読み取られる種類のSQLインジェクションです。画面に何も出ないから安全、とは言えません。原因と対策は通常のSQLインジェクションと同じで、プレースホルダを使えば成立しません。
Qエラーメッセージを隠せば防げる?
防げません。エラーを隠すと調べにくくはなりますが、ブラインドSQLインジェクションのように、エラーが出なくても情報を読み取られる場合があります。エラーを画面に出さないことは必要ですが、それとは別に、SQLを文字列連結で組み立てている箇所を直す必要があります。
Qストアドプロシージャを使えば安全?
正しく書けば、プレースホルダと同じくらい有効です。ただしOWASPは、プロシージャの中で入力を連結してSQLを組み立てる(動的SQL)と同じ問題が起きると注意しています。プロシージャの中身まで確認します。