SQL Injection Defense
On this page
What SQL Injection Is
SQL injection happens when attackers control query structure via untrusted input. The only correct defense is: prepared statements + parameter binding. Never build SQL by concatenating user input.
The Dangerous Pattern
<?php $id = $_GET["id"] ?? "0"; // Dangerous: $sql = "SELECT id, title FROM items WHERE id = " . $id;
The Correct Pattern (Bind Values)
<?php
$id = (int)($_GET["id"] ?? 0);
$stmt = $pdo->prepare("SELECT id, title FROM items WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch();
LIKE Queries Safely
You can still use LIKE with binding. You just bind the full pattern.
<?php
$q = $_GET["q"] ?? "";
$stmt = $pdo->prepare("SELECT id, title FROM items WHERE title LIKE ? LIMIT 20");
$stmt->execute(["%" . $q . "%"]);
Whitelist for ORDER BY and Identifiers
You cannot bind column names. Use a whitelist map for sorting/filtering identifiers.
<?php $sort = $_GET["sort"] ?? "new"; $map = [ "new" => "id DESC", "old" => "id ASC", "title" => "title ASC", ]; $orderBy = $map[$sort] ?? $map["new"]; $sql = "SELECT id, title FROM items ORDER BY " . $orderBy . " LIMIT 20"; $rows = $pdo->query($sql)->fetchAll();
Production Tip
Bind every user-provided value. Whitelist identifiers. Add validation (int casting, length limits). Log suspicious patterns and rate limit abuse-prone endpoints.