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 +
(PostgreSQL):pg
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は信用できる入力だけで動いているか?」を問い直す習慣が、最強の防御になります。