SQLインジェクション防止テクニック
パラメータ化クエリ、プリペアドステートメント、ORM、入力バリデーションでSQLインジェクション攻撃からアプリケーションを保護する必須セキュリティ対策を解説します。
Security
詳細な説明
SQLインジェクション防止テクニック
SQLインジェクションは、最も危険で一般的なWebアプリケーション脆弱性の1つです。信頼できない入力が適切な処理なしにSQLクエリに組み込まれた場合に発生し、攻撃者がクエリのロジックを操作できるようになります。
脆弱性の例
-- 危険: 文字列連結
query = "SELECT * FROM users WHERE email = '" + userInput + "'";
-- userInputが: ' OR '1'='1' -- の場合
-- クエリは以下になる:
SELECT * FROM users WHERE email = '' OR '1'='1' --'
-- これはすべてのユーザーを返す
パラメータ化クエリ(解決策)
# Python (psycopg2)
cursor.execute("SELECT * FROM users WHERE email = %s", (user_input,))
// Node.js (pg)
client.query("SELECT * FROM users WHERE email = $1", [userInput])
// Java (JDBC)
PreparedStatement stmt = conn.prepareStatement(
"SELECT * FROM users WHERE email = ?");
stmt.setString(1, userInput);
パラメータはクエリテキストとは別に送信され、SQLコードとして解釈されることはありません。
ORMによる保護
ほとんどのORMはデフォルトでパラメータ化クエリを使用します:
# Django ORM(安全)
User.objects.filter(email=user_input)
# SQLAlchemy(安全)
session.query(User).filter(User.email == user_input)
警告: 生のSQLを許可するORMでも、ユーザー入力にはパラメータ化が必要です。
多層防御
- パラメータ化クエリ: 主要な防御策。妥協の余地なし
- 入力バリデーション: 期待される形式のホワイトリスト(メールの正規表現、数値範囲)
- 最小権限: データベースアカウントには必要な権限のみを付与する
- WAFルール: Webアプリケーションファイアウォールで一般的なインジェクションパターンを検知する
- エスケープ: パラメータ化が不可能な場合の最終手段のみ
- エラー処理: データベースのエラーメッセージをエンドユーザーに公開しない
一般的なインジェクションポイント
- ログインフォーム(認証バイパス)
- 検索フィールドとフィルタ
- URLパラメータとクエリ文字列
- HTTPヘッダー(User-Agent、Referer)
- APIのJSONおよびXMLペイロード
SQLインジェクションは20年以上にわたりWebの脆弱性第1位であり続けています。パラメータ化クエリは決定的な解決策であり、ユーザー入力がSQLに触れるすべての箇所で使用しなければなりません。
ユースケース
開発チームが、レガシーアプリケーションの文字列連結によるSQLクエリをすべてパラメータ化されたプリペアドステートメントにリファクタリングし、コードベース全体のSQLインジェクション脆弱性を排除する場面。