SQLインジェクションとパラメータ化クエリ
常にPDOのプリペアドステートメントを使ってインジェクションのリスクをなくします
「SQLインジェクションとパラメータ化クエリ」はCoddyKit上の無料PHP Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPHP Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 PHP Academyコースには全4レッスンが含まれています。
SQLインジェクションとは
SQLインジェクションとは、ユーザーから提供されたデータをSQLクエリに直接埋め込むことで、攻撃者がクエリを操作し、データへのアクセス、変更、削除を可能にする攻撃です。
典型的な例
ユーザー入力をSQLに連結します:
<?php
// VULNERABLE: attacker enters username = "' OR '1'='1"
$sql = "SELECT * FROM users WHERE username = '".$_GET["username"]."'";
// Becomes: SELECT * FROM users WHERE username = '' OR '1'='1'
// Returns ALL users!データ流出の例
攻撃者はUNION SELECTを使って、他のテーブルからデータを流出させます。
// Input: ' UNION SELECT username, password FROM admin_users--
// This appends a second SELECT returning admin credentialsプリペアドステートメントが解決策
プリペアドステートメントでは、データが提供される前にクエリ構造が固定されます。データベースは、バインドされた値をすべてリテラルデータとして扱い、SQLコードとして扱うことはありません。
<?php
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$_GET["username"]]);
// Safe even if username = "' OR 1=1--"名前付きプレースホルダー
名前付きプレースホルダーは、特にパラメーターが複数ある場合に、より明確になります。
<?php
$stmt = $pdo->prepare(
"SELECT * FROM users WHERE email = :email AND active = :active"
);
$stmt->execute([":email" => $email, ":active" => true]);Eloquentはデフォルトで安全
Laravel Eloquentは、標準的なすべてのクエリビルダー操作で、内部的にPDOのプリペアドステートメントを使用します。
<?php
// Safe:
User::where("email", $email)->first();
// UNSAFE: raw query with user input!
DB::select("SELECT * FROM users WHERE email = ".$email);生SQLクエリ
Laravelで生SQLを使用する必要がある場合は、必ずパラメーターバインディングを使用してください。
<?php
// Safe raw query:
$users = DB::select("SELECT * FROM users WHERE email = ?", [$email]);
// Or with named bindings:
$users = DB::select("SELECT * FROM users WHERE email = :email", [":email" => $email]);LIKE句のインジェクション
LIKE句には特別な処理が必要です。ワイルドカード文字(%、_)は、バインドする前に手動でエスケープする必要があります。
<?php
$search = str_replace(["%", "_", "\\"], ["\%", "\_", "\\\\"], $userInput);
$stmt = $pdo->prepare("SELECT * FROM products WHERE name LIKE ?");
$stmt->execute(["%$search%"]);ORDER BYインジェクション
カラム名とORDER BYの方向はパラメーター化できません。ホワイトリストと照合して検証してください。
<?php
$allowedColumns = ["name", "price", "created_at"];
$col = in_array($request->sort, $allowedColumns) ? $request->sort : "name";
$dir = $request->dir === "desc" ? "desc" : "asc";
// Then safely build the query stringストアドプロシージャ
ストアドプロシージャも、内部で入力を連結している場合は脆弱になる可能性があります。必ずパラメーター化された呼び出しを使用してください。
最小権限の原則
PHPから接続するデータベースユーザーには、必要なテーブルに対するSELECT/INSERT/UPDATE/DELETEだけを許可し、CREATE、DROP、管理者権限は決して付与しないでください。
概要
バインドパラメーター付きのプリペアドステートメントを必ず使用してください。ユーザー入力をSQLに連結しないでください。ORDER BYとカラム名はホワイトリストと照合して検証してください。エミュレートプリペアを無効にしたPDOを使用してください。
確認問題
SQLインジェクションを防ぐ正しい方法は何ですか?
よくある質問
「SQLインジェクションとパラメータ化クエリ」レッスンは無料ですか?
はい。「SQLインジェクションとパラメータ化クエリ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、PHP Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 PHP Academyコースには全4レッスンが含まれています。
「SQLインジェクションとパラメータ化クエリ」で何を学びますか?
常にPDOのプリペアドステートメントを使ってインジェクションのリスクをなくします ブラウザで直接実行するハンズオンコードでPHP Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
PHP Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPHP Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「SQLインジェクションとパラメータ化クエリ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPHP Academyレッスンでコードを書いて実行できますか?
はい。すべてのPHP Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- クロスサイトスクリプティング(XSS)の防止
- SQLインジェクションとパラメータ化クエリ
- CSRF対策
- パスワードの安全な保存