SQLインジェクションとは?攻撃の仕組み・実例・対策をわかりやすく解説

SQLインジェクションとは?一言でいうと「入力欄からデータベースを不正操作する攻撃」

SQLインジェクション(SQL Injection)は、Webアプリケーションの入力欄に悪意のあるSQL文を紛れ込ませ、データベースを不正に操作する攻撃手法です。OWASP Top 10でも常に上位にランクインする、最も危険かつ最も発生頻度の高い脆弱性の一つです。

たとえるなら、図書館の検索端末を想像してください。通常は「本のタイトル」を入力して検索しますが、もし検索欄に「全会員の個人情報を表示せよ」という命令を入力でき、それがそのまま実行されてしまったら?——これがSQLインジェクションの本質です。

攻撃の仕組み:なぜSQL文が注入できるのか

SQLインジェクションが成立する根本原因は、ユーザーの入力値がSQL文にそのまま埋め込まれる設計にあります。

脆弱なコードの例

たとえば、ログイン画面で以下のようなSQL文を組み立てているとします。

SELECT * FROM users WHERE username = '入力値' AND password = '入力値'

ここでユーザー名欄に ' OR '1'='1 と入力すると、SQL文は次のように変化します。

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = ''

'1'='1' は常にtrueなので、パスワードを知らなくても全ユーザーの情報が返されてしまいます。

SQLインジェクションで何ができてしまうのか

攻撃パターン 内容 危険度
データ漏洩 個人情報、クレジットカード情報、パスワードなどの窃取 極めて高い
認証バイパス パスワードなしでの管理者ログイン 極めて高い
データ改ざん 商品価格の変更、ユーザー権限の昇格 高い
データ削除 DROP TABLE によるテーブル丸ごと削除 極めて高い
OS コマンド実行 データベースサーバー上でのシステムコマンド実行(一部DBMS) 致命的

SQLインジェクションの主な種類

1. インバンドSQLインジェクション

最も基本的なタイプで、攻撃結果が画面上にそのまま表示されるものです。UNION句を使って別テーブルの情報を取得する「UNION攻撃」や、エラーメッセージから情報を得る「エラーベース」が含まれます。

2. ブラインドSQLインジェクション

攻撃結果が直接画面に表示されない場合の手法です。true/falseの応答の違いから情報を推測する「ブールベース」と、レスポンスの遅延時間から判断する「タイムベース」があります。

3. アウトオブバンドSQLインジェクション

DBサーバーからDNSリクエストやHTTPリクエストを外部に送信させ、そこにデータを載せて窃取する高度な手法です。

具体的な対策:開発者が実装すべき防御策

最重要:プリペアドステートメント(パラメータ化クエリ)

SQLインジェクション対策で最も効果的かつ必須の防御策です。SQL文の構造とデータを分離し、入力値がSQL命令として解釈されることを防ぎます。

// 脆弱(文字列結合)
query = "SELECT * FROM users WHERE id = " + userId;

// 安全(プリペアドステートメント)
query = "SELECT * FROM users WHERE id = ?";
stmt.setInt(1, userId);

Java、Python、PHP、Node.jsなど、すべての主要言語でプリペアドステートメントがサポートされています。

入力値のバリデーション

数値が期待される項目には数値チェック、メールアドレスにはフォーマット検証など、ホワイトリスト方式で入力を制限します。ただし、バリデーションだけでは不十分で、プリペアドステートメントとの併用が前提です。

最小権限の原則

データベース接続ユーザーには必要最小限の権限のみを付与します。Webアプリ用のDBユーザーにDROPやCREATE権限は不要です。万が一攻撃されても被害を最小化できます。

WAF(Web Application Firewall)

WAFはHTTPリクエストを検査し、SQLインジェクションのパターンを検出・遮断します。根本対策ではありませんが、多層防御の一環として有効です。

実際に起きた重大インシデント

SQLインジェクションは現実に甚大な被害を生んでいます。2011年のソニー・ピクチャーズへの攻撃では数百万件の個人情報が流出し、大規模な情報漏洩事件となりました。日本でも多くの企業や自治体のWebサイトがSQLインジェクション被害に遭っています。

こうした事例の多くは、プリペアドステートメントを使うだけで防げたものです。

よくある質問(FAQ)

Q. ORMを使っていればSQLインジェクションは起きませんか?

ORMのメソッドを正しく使う限りは安全です。ただし、ORMでも生のSQL文を直接記述する機能(raw query)を使う場合はSQLインジェクションのリスクがあります。ORMだからといって油断は禁物です。

Q. NoSQLデータベースでも同様の攻撃はありますか?

はい。MongoDBなどのNoSQLにもNoSQLインジェクションと呼ばれる類似攻撃が存在します。JSONクエリに悪意のあるオペレータ($gtなど)を注入する手法で、対策の考え方はSQLインジェクションと同様です。

Q. SQLインジェクションの脆弱性をテストするには?

OWASP ZAP(無料)やBurp Suite(有料)などのセキュリティテストツールで自動検出できます。また、sqlmapというオープンソースツールはSQLインジェクション検出に特化しています。本番環境ではなくテスト環境で実施してください。

まとめ:SQLインジェクションはプリペアドステートメントで防げる

SQLインジェクションは20年以上前から知られる古典的な攻撃ですが、いまだに多くの被害が発生しています。防御の基本はシンプルで、プリペアドステートメントを徹底し、入力バリデーションと最小権限の原則を組み合わせることです。Webアプリケーション開発者にとって、SQLインジェクション対策は最初に習得すべきセキュリティスキルといえます。

コメント