Web セキュリティ

SQL インジェクション

約 4 分で読めます

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 インジェクションによる被害は、データの窃取にとどまりません。

  • データの窃取: ユーザーの個人情報、認証情報、クレジットカード番号など、データベースに格納されたすべてのデータが漏洩する可能性がある
  • データの改ざん・削除: UPDATEDELETE 文を注入し、データを改ざんまたは削除する。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 で防御する。被害はユーザーのブラウザ上で発生する。

関連用語

関連記事