SQLインジェクションとは:プレースホルダーで防ぐ基本

入門 | 11分 で読める | 2026.06.17

公式ドキュメント

SQLインジェクションは、Webアプリの代表的な脆弱性です。フォームやURLから受け取った値をSQLに直接混ぜると、攻撃者が意図しないSQLを実行できる場合があります。

一言でいうと

SQLインジェクションは、ユーザー入力をSQL文字列として混ぜてしまい、SQLの意味を攻撃者に書き換えられる問題です。

危険な考え方

ログイン処理で、次のようにSQLを文字列連結で作ると危険です。

const sql =
  "SELECT * FROM users WHERE email = '" + email + "' AND password = '" + password + "'";

ユーザーが普通のメールアドレスを入力する前提なら動くかもしれません。しかし、入力値にSQLの一部として解釈される文字列が入ると、条件が変わる可能性があります。

何が問題なのか

SQLでは、文字列、条件、コメントなどに意味があります。入力値をそのままSQLに連結すると、データとして扱うべき文字列が、SQLの命令として解釈されることがあります。

攻撃の具体的な文字列を覚える必要はありません。初心者がまず覚えるべきことは、次の一点です。

ユーザー入力をSQL文字列に直接連結しないことが基本です。

プレースホルダー

安全な基本は、プレースホルダーやパラメータ化クエリを使うことです。

const sql = "SELECT * FROM users WHERE email = $1";
const values = [email];

この形では、SQLの構造と入力値を分けて渡します。データベースドライバは、email をSQL文の一部ではなく値として扱います。

データベースやライブラリによって記法は異なります。

系統プレースホルダー例
PostgreSQL系$1, $2
MySQL系?
SQLite系?, :name
ORMライブラリのAPIで値を渡す

ORMを使えば絶対安全か

ORMやクエリビルダーを使うと、プレースホルダーを自然に使いやすくなります。ただし、raw SQLを文字列連結で組み立てると危険は残ります。

// よい方向性: 値を別に渡す
const user = await db.user.findUnique({
  where: { email }
});

一方で、ORMでも生SQLを直接書く機能を使うときは注意が必要です。

入力チェックとの違い

入力チェックも重要ですが、SQLインジェクション対策の中心はプレースホルダーです。

対策役割
入力チェック想定外の形式を早めに弾く
プレースホルダーSQL構造と値を分離する
権限分離被害範囲を小さくする
ログ監視異常なアクセスに気づく

入力チェックだけに頼ると、抜け漏れが起きる可能性があります。

実務で守ること

  • SQLを文字列連結で作らない
  • プレースホルダーを使う
  • ORMのraw SQL機能を使うときは値の渡し方を確認する
  • DBユーザーに過剰な権限を与えない
  • エラーメッセージにSQLや内部情報を出しすぎない

SQLインジェクション対策は、入力を頑張って無害化するより、SQL構造と値を分ける設計にすることが重要です。

よくある誤解

誤解実際
個人開発なら関係ない公開すれば攻撃対象になります
入力チェックすれば十分プレースホルダーが基本です
ORMなら何を書いても安全raw SQLの使い方次第で危険です
SELECTだけなら安全情報漏えいにつながる可能性があります

まとめ

SQLインジェクションは、ユーザー入力がSQLの命令として解釈されることで起きます。基本対策は、ユーザー入力をSQL文字列に直接連結せず、プレースホルダーやパラメータ化クエリで値として渡すことです。

参考リソース

← 一覧に戻る
PR
PR
PR
PR