SQL Injection
概要
- 脆弱性の名前: SQL Injection
- 問題の要点: Webアプリケーションが、ユーザーからの入力を適切に検証せずにSQLクエリに組み込むことで、攻撃者がデータベースを不正に操作できる脆弱性。
- よくある発生シーン: フォーム入力、URLパラメータ、Cookieなど、ユーザーが提供するデータがデータベースクエリで使用される箇所
背景
SQL Injectionは、Webアプリケーション黎明期から存在する古典的な脆弱性ですが、未だに多くのWebサイトで発見されています。
データベースへのアクセスを伴うWebアプリケーションは多いため、SQL Injectionの対策が不十分な場合、深刻なセキュリティリスクとなります。
過去には、SQL Injectionを悪用した大規模な情報漏洩事件が多数発生しており、企業や組織に大きな損害を与えています。
セキュリティ上のリスク
- データベース内の機密情報(個人情報、クレジットカード情報など)の漏洩。
- データベースの改ざんや破壊。
- Webサイトの改ざんや不正なコンテンツの表示。
- データベースサーバーのOSコマンド実行。
対処方法の具体例
PHP
誤った設定例
ユーザーからの入力をエスケープせずにSQLクエリに組み込む例:
<?php
// 誤った例: エスケープ処理なし
$username = $_GET['username'];
$query = "SELECT * FROM users WHERE username = '$username'";
$result = mysqli_query($conn, $query);
?>
正しい設定例
プリペアドステートメントを使用し、ユーザーからの入力を安全に処理する例:
<?php
// 正しい例: プリペアドステートメントを使用
$username = $_GET['username'];
$stmt = mysqli_prepare($conn, "SELECT * FROM users WHERE username = ?");
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
?>
Python
誤った設定例
ユーザーからの入力をエスケープせずにSQLクエリに組み込む例:
# 誤った例
username = request.args.get('username')
query = "SELECT * FROM users WHERE username = '%s'" % username
cursor.execute(query)
正しい設定例
プレースホルダーを使用し、ユーザーからの入力を安全に処理する例:
# 正しい例
username = request.args.get('username')
query = "SELECT * FROM users WHERE username = %s"
cursor.execute(query, (username,))
Java
誤った設定例
ユーザーからの入力をエスケープせずにSQLクエリに組み込む例:
// 誤った例
String username = request.getParameter("username");
String query = "SELECT * FROM users WHERE username = '" + username + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
正しい設定例
プリペアドステートメントを使用し、ユーザーからの入力を安全に処理する例:
// 正しい例
String username = request.getParameter("username");
String query = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
データベース
誤った設定例
データベースユーザーに過剰な権限を与えてしまう例:
正しい設定例
データベースユーザーに必要な最小限の権限のみを付与する:
AWS
誤った設定例
RDSインスタンスへのアクセス制御が不十分な例:
正しい設定例
セキュリティグループを使用して、RDSインスタンスへのアクセスを制限する:
検出方法
OWASP ZAPでの出力例
- Alert 名: SQL Injection
- リスク: High
- URL: SQL Injectionが可能なURL
- パラメータ: 悪用可能なパラメータ
- 詳細: 脆弱性が存在する場所と、悪用方法に関する情報
手動再現例
- WebサイトのフォームやURLパラメータに、SQL Injectionのテスト文字列(例:
' OR '1'='1
)を入力します。 - エラーメッセージやWebサイトの挙動を観察し、SQL Injectionが成功するかどうかを確認します。
まとめ
- CVSS 基本値: 10.0 (Critical)
- 運用チームや開発者が意識すべきポイント:
- ユーザーからの入力を常に検証し、エスケープする。
- プリペアドステートメントやパラメータ化されたクエリを使用する。
- データベースユーザーに必要な最小限の権限のみを付与する。
- Webアプリケーションファイアウォール(WAF)を導入し、SQL Injection攻撃を防御する。
- 定期的にペネトレーションテストを実施し、脆弱性を特定する。
- 再発防止:
- 開発プロセス全体でセキュリティを考慮する(Security by Design)。
- コードレビューを実施し、SQL Injectionのリスクを早期に発見する。
- 自動脆弱性診断ツールを導入し、定期的にスキャンを行う。
- 開発者向けのセキュリティトレーニングを実施する。
補足資料・参考URL
以上の対策と検出方法を活用して、SQL Injectionのリスクを低減してください。