Topiqlo ロゴ

SQLインジェクション対策

公開日: 2025/06/03

SQLインジェクション対策:基本から実践まで徹底解説

はじめに

SQLインジェクションは、Webアプリケーションにおける最も古く、最も深刻な脆弱性のひとつです。
ユーザーの入力をそのままSQLに埋め込むことで、データの読み取り・改ざん・削除などが可能になってしまいます。
本記事では、SQLインジェクションの原理と、確実な対策方法を言語別に紹介します。

基本情報・概要

SQLインジェクションとは、悪意のあるSQL構文を入力として注入し、不正なクエリを実行させる攻撃です。
例:

1 OR 1=1
のような入力で全件取得される

  • 攻撃例:ログイン認証回避、全件取得、データ削除、DB破壊

  • 影響範囲:ユーザー情報流出、システム停止、データ損失など

  • 脆弱な例:

      const query = "SELECT * FROM users WHERE id = " + req.query.id;
    

比較・分類・特徴の表形式まとめ

対策方法内容効果・備考
プレースホルダー(?)値をクエリとは分離して処理する最も基本かつ強力な対策
ORMの使用Sequelize, Prisma, SQLAlchemy など自動的にバインディングを処理
ホワイトリスト検証テーブル名や列名などを限定的に受け入れる動的SQL生成時の対策として有効
入力値バリデーション数値や文字列の形式をチェックする補助的な対策。単独では不十分
DBアカウント分離・権限制限アプリ用ユーザーに読み取り権限だけを与える万一侵入されても被害を限定可能

深掘り解説(言語別実装)

  • Node.js +

    pg
    (PostgreSQL)

      const result = await client.query(
          "SELECT * FROM users WHERE id = $1",
          [req.query.id]
      );
    
  • Python +

    psycopg2

      cur.execute("SELECT * FROM users WHERE id = %s", (user_id,))
    
  • PHP(PDO)

      $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
      $stmt->execute([$id]);
    
  • Sequelize(Node.js ORM)

      const user = await User.findOne({ where: { id } });
    
  • ホワイトリストの例(動的列名)

      const allowedFields = ["name", "email"];
      if (!allowedFields.includes(field)) throw Error("Invalid field");
      db.query(`SELECT ${field} FROM users WHERE id = ?`, [id]);
    

応用・発展的な使い方

  • Webアプリファイアウォール(WAF)との併用
  • SQLログ監査ツールの導入
  • テストフェーズでのインジェクションテスト(ZAP, Burp Suiteなど)
  • CIにSAST(静的解析)を導入して脆弱性の早期発見

よくある誤解と注意点

  • プレースホルダーを使っていても、列名やテーブル名にユーザー入力を直接使うのはNG
  • ORMを使っているからといって自動生成SQLを過信しない
  • LIKE句の中でもエスケープ処理を忘れずに(例:
    %
    _
    の扱い)

まとめ

SQLインジェクションは、小さな不注意から甚大な被害につながる典型的な脆弱性です。
プレースホルダー・ORM・入力検証・権限制御などを組み合わせて、入口から出口までセキュアに保ちましょう。
常に「このSQLは信用できる入力だけで動いているか?」を問い直す習慣が、最強の防御になります。