説明
外部入力がデータではなくSQL構文の一部として解釈されると、SQLインジェクションが発生します。攻撃者はクエリの条件や操作を変更できます。影響はデータベースアカウントの権限と利用できる機能によって変わります。
想定される影響
- データベースの機能と権限が許す場合のOSコマンド実行
- データベース内の機密情報の漏えい
- なりすましや権限昇格
- 認証・アクセス制御の回避
- データの不正な変更や削除
対処方法
PreparedStatementやJdbcTemplateのパラメーターバインドで、値とSQL構文を分けてください。入力を連結してから準備するだけでは不十分です。- ORMでも、SQL・JPQL・HQLを文字列で組み立てると同じ危険があります。対応するバインドAPIを使ってください。
- テーブル名、列名、並べ替え方向など値パラメーターにできない要素は、サーバーが管理する許可リストから選んでください。
- 入力の形式と長さを検証し、データベースアカウントには必要最小限の権限を付与してください。
例
JdbcTemplateでユーザーレコードを取得する抜粋であり、ログイン実装ではありません。パスワード検証とレコードを読む権限の確認は別途行ってください。
変更前
java
String query = "SELECT id, username FROM users WHERE username = '" + username + "'";
jdbcTemplate.queryForList(query);
変更後
java
String query = "SELECT id, username FROM users WHERE username = ?";
jdbcTemplate.queryForList(query, username);
変更前はusernameをSQL文字列に連結します。変更後は検索用のqueryForList()に値を分けて渡すため、usernameがSQL構文として解釈されません。
関連CVE
- CVE-2023-32530: セキュリティダッシュボードの証明書フィールドによるSQLインジェクション
- CVE-2021-42258: 時間・請求管理ソフトウェアのSQLインジェクション(CISA KEV掲載)
- CVE-2021-27101: ファイル転送ソフトウェアのHostヘッダーによるSQLインジェクション(CISA KEV掲載)