一覧へ

SQLインジェクションとパラメータ化されたクエリ

SQLインジェクションがどのように機能するかを理解し、パラメータ化されたクエリで完全に防ぐ方法を学びます。

中級
|
7
|
検証済み (2026-07)
進捗0/55 (0%)

SQLインジェクションとパラメータ化されたクエリ

このトピックを修了すると

SQLインジェクションがどのように機能するかを説明でき、パラメータ化されたクエリを使用して防御するコードを作成できます。


SQLインジェクションとは

SQLインジェクションは、ユーザー入力にSQLコードを挿入してデータベースを操作する攻撃です。Webセキュリティ攻撃の中でも最も古く、最も危険で、現在でも最も一般的な攻撃です。


攻撃の仕組み

ログインフォームを考えてみましょう。ユーザーがメールアドレスを入力すると、サーバー側で次のように処理されます。

javascript
// ❌ 危険なコード — 入力を直接SQLに挿入
const email = req.body.email;
const sql = `SELECT * FROM users WHERE email = '${email}'`;
connection.query(sql);

正常な入力: hoon@example.com

sql
SELECT * FROM users WHERE email = 'hoon@example.com'
-- 正常に動作

攻撃的な入力: ' OR '1'='1

sql
SELECT * FROM users WHERE email = '' OR '1'='1'
-- '1'='1'は常に真であるため、すべてのユーザーデータが返される!

より危険な攻撃: '; DROP TABLE users; --

sql
SELECT * FROM users WHERE email = ''; DROP TABLE users; --'
-- セミコロンを使用して最初のクエリを終了し、テーブル削除コマンドを実行
-- --は残りをコメントアウト

重要な点: ユーザー入力がSQLの構造自体を変更することが問題です。


防御策:パラメータ化されたクエリ

パラメータ化されたクエリ(Prepared Statement)は、SQLの構造とデータを分離します。

javascript
// ✅ 安全なコード — プレースホルダーを使用
const email = req.body.email;
connection.query(
  'SELECT * FROM users WHERE email = ?',
  [email]
);

攻撃的な入力 ' OR '1'='1 が入力された場合でも:

sql
SELECT * FROM users WHERE email = '\' OR \'1\'=\'1'
-- すべてが1つの文字列値として処理される。SQLの構造は変更されない。

データベースエンジンはまずSQLの構造を解析し、次に ? の場所に値を安全に代入します。値がどれほど異常であっても、SQLコマンドとして解釈されません。


言語別のパラメータ化パターン

Node.js (mysql2)

javascript
// ? プレースホルダー
connection.query('SELECT * FROM users WHERE id = ?', [userId]);
connection.query(
  'INSERT INTO users (name, email) VALUES (?, ?)',
  [name, email]
);

Python (sqlite3 / psycopg2)

python
# ? プレースホルダー (sqlite3)
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
# %s プレースホルダー (psycopg2 / MySQL Connector)
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

Java (JDBC)

java
PreparedStatement stmt = conn.prepareStatement(
    "SELECT * FROM users WHERE id = ?"
);
stmt.setInt(1, userId);
ResultSet rs = stmt.executeQuery();

構文は異なりますが、原理は同じです:SQLとデータを分離します。


追加の防御層

パラメータ化されたクエリが最も重要ですが、追加の防御層も存在します。

方法役割
パラメータ化されたクエリ主要な防御 — SQLの構造を保護
入力検証メールアドレスの形式、数値の範囲など、事前フィルタリング
最小権限の原則DBアカウントに必要な権限のみを付与(DELETEが不要な場合は削除)
ORMの使用Sequelize、Prismaなどが内部的にパラメータ化を適用

最も重要なこと:ユーザー入力をSQL文字列に直接連結しないこと。 この1つのルールを守るだけで、SQLインジェクションは発生しません。


💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...