画像ツール一覧

SQLインジェクション

SQL Injection

セキュリティ

Webアプリケーションの脆弱性を突くサイバー攻撃の一つ。ユーザーの入力欄にデータベースを操作するための不正な命令(SQL文)を紛れ込ませ、データの漏洩や改ざん、削除を意図的に引き起こす非常に危険な手法です。

🐾 猫で例えると?

給餌器の受け皿へ顔を向けて立つ茶トラ
給餌器の入口から考える、入力値と命令の境界

給餌器のそばで、受け皿に顔を向ける茶トラ。ここで、注文を書いて渡す入口に「ごはんを一つ」という値だけでなく、機械の設定を変える命令まで入れられると想像してみましょう。SQLインジェクションでは、入力を値として扱う境界が崩れ、SQLの命令の一部として解釈されることが問題です。入力をSQLの構文へつなげず、値として渡す設計が必要です。

🐾 PR

💻 IT現場における「SQLインジェクション」とは?

プログラミングの現場において、SQLインジェクション対策は「絶対に避けては通れない基本中の基本」です。検索フォームやログイン画面など、ユーザーが自由に入力できる箇所はすべて攻撃の対象になり得ます。

対策が不十分な場合、本来見せてはいけないデータの取得や、許可していない変更・削除につながるおそれがあります。影響する範囲はSQLの組み立て方とDB接続権限によって変わるため、入力の見た目だけで安全と判断せず、命令と値を分けて扱います。

⚠️ SQLインジェクションの仕組みと注意点

ユーザー入力をSQLへ連結すると、引用符などで入力欄の値がSQLの条件式に解釈される場合があります。結果として本来返すべきでない行を読めたり、認証条件を変えられたりします。具体的な影響はSQLの構造とDB接続ユーザーの権限によって異なります。

プレースホルダー(バインド機構)を使った防御

値を渡す箇所では、命令文の形を先に用意するプリペアドステートメントを使います。値を入れる指定箇所(プレースホルダー)へデータを別に渡し、命令と値を分離します。次はPHPからデータベースへ接続するPDOと、usersテーブルが用意され、usernameが文字列として検証済みという前提の検索例です。ログイン機能全体の実装ではありません。

// PHP (PDO) での安全な実装例
// 危険な例(絶対ダメ!):入力値をそのまま結合している
// $sql = "SELECT * FROM users WHERE name = '" . $_POST['username'] . "'";

// 安全な例:プレースホルダー(:name)を使用する
$sql = "SELECT * FROM users WHERE name = :name";
$stmt = $pdo->prepare($sql);

// 入力値は「単なるデータ」としてバインドされるため、不正なSQLコマンドは実行されない
$stmt->bindValue(':name', $_POST['username'], PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll();

値はパラメーターで渡せますが、テーブル名や並べ替えに使う列名を同じ方法で指定できるとは限りません。例えば並び順を選ばせる場合は、あらかじめ用意した列名の許可リストから選び、入力を直接SQLへ連結しないようにします。

🛠️ SQLインジェクションを防ぐためのポイント

現場でセキュアなシステムを構築するための基本的な防御策です。どれか一つではなく、複数の対策を組み合わせる多層防御が重要です。

給餌器へ手を差し込む茶トラの例えでは、受け取り口から内部の動作へ干渉しようとする点がポイントです。SQLでは入力値が命令に混ざることを防ぎます。値を文字列連結で埋め込まず、プレースホルダーへ渡す形になっているかを確認しましょう。入力チェックやWAFを追加しても、SQLの組み立て方そのものの修正は必要です。