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でも、ユーザー入力にはパラメータ化が必要です。

多層防御

  1. パラメータ化クエリ: 主要な防御策。妥協の余地なし
  2. 入力バリデーション: 期待される形式のホワイトリスト(メールの正規表現、数値範囲)
  3. 最小権限: データベースアカウントには必要な権限のみを付与する
  4. WAFルール: Webアプリケーションファイアウォールで一般的なインジェクションパターンを検知する
  5. エスケープ: パラメータ化が不可能な場合の最終手段のみ
  6. エラー処理: データベースのエラーメッセージをエンドユーザーに公開しない

一般的なインジェクションポイント

  • ログインフォーム(認証バイパス)
  • 検索フィールドとフィルタ
  • URLパラメータとクエリ文字列
  • HTTPヘッダー(User-Agent、Referer)
  • APIのJSONおよびXMLペイロード

SQLインジェクションは20年以上にわたりWebの脆弱性第1位であり続けています。パラメータ化クエリは決定的な解決策であり、ユーザー入力がSQLに触れるすべての箇所で使用しなければなりません。

ユースケース

開発チームが、レガシーアプリケーションの文字列連結によるSQLクエリをすべてパラメータ化されたプリペアドステートメントにリファクタリングし、コードベース全体のSQLインジェクション脆弱性を排除する場面。

Try It — SQL Formatter

フルツールを開く