SQL インジェクション
約 4 分で読めます
最終更新: 2026-01-22
SQL インジェクションとは
SQL インジェクションとは、Web アプリケーションのデータベースクエリにユーザー入力が適切に処理されずに組み込まれることで、攻撃者が任意の SQL 文を実行できてしまう脆弱性です。OWASP Top 10 に長年ランクインし続けている最も危険な Web 脆弱性の 1 つであり、データベース内の全データの窃取、改ざん、削除、さらにはサーバーの OS コマンド実行にまで被害が及ぶ可能性があります。
1998 年に初めて公に報告されて以来、四半世紀以上が経過した現在でも、SQL インジェクションは Web アプリケーションに対する攻撃の主要な手法であり続けています。根本的な対策が明確であるにもかかわらず、実装の不備により脆弱性が残存するケースが後を絶ちません。
攻撃の原理と種類
SQL インジェクションは、アプリケーションが SQL クエリを文字列連結で組み立てる際に発生します。例えば、ログインフォームで入力されたユーザー名を SELECT * FROM users WHERE name = '入力値' のようにクエリに直接埋め込む場合、攻撃者が入力値に ' OR '1'='1 と入力すると、WHERE 句が常に真となり、認証をバイパスできます。
主な攻撃の種類
- UNION ベース:
UNION SELECTを注入して、本来アクセスできないテーブルのデータを取得する。カラム数と型を合わせる必要があるが、エラーメッセージやレスポンスの変化から推測可能 - エラーベース: 意図的にエラーを発生させ、エラーメッセージに含まれるデータベースの情報 (テーブル名、カラム名、データ) を読み取る
- ブラインド SQL インジェクション: エラーメッセージが表示されない場合に、真偽値の条件分岐 (Boolean-based) やレスポンス時間の差 (Time-based) を利用して、1 ビットずつ情報を抽出する
- 帯域外 (Out-of-Band): DNS リクエストや HTTP リクエストを通じて、データベースから外部サーバーにデータを送信させる
自動化ツール (sqlmap など) の存在により、高度な技術知識がなくても SQL インジェクションの検出と悪用が可能になっています。
被害の実態と影響範囲
SQL インジェクションによる被害は、データの窃取にとどまりません。
- データの窃取: ユーザーの個人情報、認証情報、クレジットカード番号など、データベースに格納されたすべてのデータが漏洩する可能性がある
- データの改ざん・削除:
UPDATEやDELETE文を注入し、データを改ざんまたは削除する。DROP TABLEでテーブル全体を削除することも可能 - 認証のバイパス: ログインクエリを操作して、パスワードを知らずに任意のアカウント (管理者を含む) としてログインする
- サーバーの制御奪取: データベースの機能 (MySQL の
LOAD_FILE、SQL Server のxp_cmdshellなど) を悪用して、OS レベルのコマンドを実行する
過去の大規模な情報漏洩事件の多くに SQL インジェクションが関与しています。WAF による検知は有効な補助策ですが、巧妙なエンコーディングやコメント挿入で WAF をバイパスする手法も知られており、根本対策の代替にはなりません。
根本的な対策
SQL インジェクションの根本対策は明確であり、正しく実装すれば脆弱性を完全に排除できます。
プリペアドステートメント (パラメータ化クエリ)
SQL 文の構造とデータを分離し、ユーザー入力が SQL の構文として解釈されることを防ぎます。これが最も確実で推奨される対策です。すべてのデータベースアクセスライブラリがプリペアドステートメントをサポートしています。
ORM の活用
ORM (Object-Relational Mapping) を使用すると、SQL を直接記述する機会が減り、SQL インジェクションのリスクが低下します。ただし、ORM の生クエリ機能やカスタムクエリを使用する場合は、プリペアドステートメントと同様の注意が必要です。
多層防御
- 最小権限の原則: アプリケーションが使用するデータベースアカウントの権限を必要最小限にする。読み取り専用の操作には読み取り専用アカウントを使用する
- 入力のバリデーション: 数値フィールドには数値のみ、メールアドレスフィールドには適切な形式のみを受け付ける。ただし、これは補助的な対策であり、プリペアドステートメントの代替にはならない
- エラーメッセージの制御: データベースのエラーメッセージをユーザーに直接表示しない。エラーベースの SQL インジェクションによる情報漏洩を防ぐ
- 脆弱性管理: 定期的なセキュリティスキャンとコードレビューで、SQL インジェクションの脆弱性を早期に発見する
- セキュリティヘッダーの設定: 直接的な SQL インジェクション対策ではないが、全体的なセキュリティ姿勢を強化する
よくある誤解
- 入力値をエスケープすれば SQL インジェクションは防げる
- エスケープ処理は実装ミスが起きやすく、文字エンコーディングの違いや特殊なケースで漏れが生じる。プリペアドステートメントは SQL の構造とデータを根本的に分離するため、エスケープ漏れのリスクがない。エスケープではなくプリペアドステートメントを使うべき。
- NoSQL データベースなら SQL インジェクションは発生しない
- SQL インジェクションは発生しないが、NoSQL インジェクションという同種の脆弱性が存在する。MongoDB では JSON クエリにユーザー入力を直接埋め込むと、クエリ演算子の注入が可能になる。データベースの種類に関係なく、ユーザー入力の適切な処理は必須。
SQL インジェクションと XSS の比較
SQL インジェクション
サーバー側のデータベースを標的にする。データの窃取・改ざん・削除が可能。プリペアドステートメントで根本的に防御できる。被害はサーバー側のデータに及ぶ。
XSS
クライアント側のブラウザを標的にする。Cookie 窃取やセッションハイジャックが主な被害。出力エスケープと CSP で防御する。被害はユーザーのブラウザ上で発生する。