用語集 · セキュリティ
SQL インジェクション(SQL Injection)
英語: SQL injection
別名: SQLi, SQLインジェクション, SQL インジェクション攻撃, SQL injection attack
定義
ユーザー入力が SQL クエリに文字列連結される脆弱性で、攻撃者がクエリのロジックを変えてデータを読み取り、改ざん、削除できてしまいます。
SQL インジェクション(SQLi)は、アプリケーションがユーザー入力をクエリ文字列に貼り付けて SQL 文を組み立てるときに発生します。入力に SQL 構文が含まれていると、データベースはそれをクエリの一部として実行してしまいます。クエリの内容やデータベースの権限によっては、攻撃者がログインを回避したり、ほかのユーザーのデータを読んだり、レコードを改ざんしたり、最悪の場合はサーバー上でコマンドを実行したりできます。OWASP Top 10 2021 では A03 Injection に分類されています。
例
脆弱な Java コード:
String sql = "SELECT * FROM users WHERE email = '" + email + "'";
ResultSet rs = conn.createStatement().executeQuery(sql);
email が ' OR '1'='1 の場合、クエリは次のようになります。
SELECT * FROM users WHERE email = '' OR '1'='1'
条件は常に真になるため、クエリはすべてのユーザーを返します。修正方法はパラメーター化クエリです。入力は SQL テキストとは別に送られるため、クエリの構造を変えることは決してできません。
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE email = ?");
ps.setString(1, email);
ResultSet rs = ps.executeQuery();
テスターが確認すること
書面による許可を得たうえで、テスト環境で次を行います。
- 構文を壊す。 クエリに到達しうるテキストフィールド、URL パラメーター、ヘッダー、JSON の値それぞれに、シングルクォート
'を 1 つ送信します。500エラー、データベースのエラーメッセージ、結果件数の変化があれば、入力がエスケープされないまま SQL に届いている可能性があります。 - ロジックを変える。
value' AND '1'='1とvalue' AND '1'='2を比較します。通常の値では説明できない形で 2 つのレスポンスが異なれば、入力が解釈されています。 - 目立たない入力も調べる。 ソート列、フィルター項目、検索ボックス、レポートのパラメーターは、列名をパラメーターとしてバインドできないため、動的に組み立てられていることがよくあります。
- エラー処理を確認する。 レスポンスにデータベースのエラー、テーブル名、スタックトレースが含まれていれば、それ自体が指摘事項です。
sqlmap のようなツールはより深い調査を自動化しますが、データを改ざん・削除する可能性があるため、明示的にテストを許可されたシステムに対してのみ実行してください。
検証すべき防御策
パラメーター化クエリ、または ORM があらゆる箇所で正しく使われていること。ソート列のような動的な識別子に対する許可リスト。最小権限のデータベースアカウント。そして汎用的なエラーメッセージ。入力値の検証も役立ちますが、パラメーター化の代わりにはなりません。