SQL Injection
Also Known As
SQLi
SQL attack
database injection
TL;DR
Unsanitised user input inserted directly into a SQL query, letting attackers read, modify, or delete database data.
Explanation
SQL Injection occurs when user-supplied data is concatenated into a SQL statement without parameterisation. An attacker can close the intended query early and append their own SQL — extracting every row in the database, bypassing login checks, or calling destructive commands. It is consistently the most exploited web vulnerability. The fix is always prepared statements with bound parameters; input sanitisation alone is not sufficient.
How It's Exploited
GET /users?id=1 OR 1=1--
# Returns all rows
GET /users?id=1; DROP TABLE users--
# Drops the table (if stacked queries allowed)
# Returns all rows
GET /users?id=1; DROP TABLE users--
# Drops the table (if stacked queries allowed)
Diagram
flowchart TD
INPUT[User Input<br/>' OR 1=1 --] --> CONCAT[String Concatenation<br/>SELECT * FROM users<br/>WHERE name = '' OR 1=1--']
CONCAT --> DB[(Database<br/>returns ALL rows)]
DB --> LEAK[Data Leak]
subgraph Fix
SAFE_INPUT[User Input] --> PREP[Prepared Statement<br/>? placeholder]
PREP --> BIND[Driver escapes<br/>automatically]
BIND --> SAFE_DB[(Database<br/>safe query)]
end
style LEAK fill:#f85149,color:#fff
style SAFE_DB fill:#238636,color:#fff
Common Misconception
✗ Escaping quotes is sufficient protection. It isn't — prepared statements with parameterised queries are the only reliable defence, because escaping is encoding-dependent and easy to get wrong.
Why It Matters
SQL injection is the most exploited web vulnerability — a single unsanitised input can expose an entire database, bypass authentication, or destroy data. Parameterised queries cost nothing to implement and eliminate the risk entirely.
Common Mistakes
- Using string escaping (addslashes, mysql_real_escape_string) instead of prepared statements — escaping is bypassable.
- Parameterising values but dynamically concatenating table or column names into queries.
- Assuming an ORM makes you immune — raw query methods like DB::statement() still allow injection.
- Forgetting second-order injection: safely stored input can re-enter a query unsafely later.
Code Examples
✗ Vulnerable
$id = $_GET['id'];
$users = $db->query("SELECT * FROM users WHERE id = $id");
✓ Fixed
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute([':id' => (int) $_GET['id']]);
$user = $stmt->fetch();
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
13 Mar 2026
Edited
22 Mar 2026
Views
36
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Perplexity 10
Amazonbot 9
Ahrefs 5
Google 2
Qwen 1
Also referenced
How they use it
crawler 26
crawler_json 1
Related categories
⚡
DEV INTEL
Tools & Severity
🔴 Critical
⚙ Fix effort: Low
⚡ Quick Fix
Replace $db->query("...{$var}") with $pdo->prepare('...:p') + execute([':p'=>$var])
📦 Applies To
PHP 5.1+
web
cli
queue-worker
🔗 Prerequisites
🔍 Detection Hints
->query("...{$_GET" or ->query("...$_POST or ->query("...$variable
Auto-detectable:
✓ Yes
phpstan
psalm
semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Low
✗ Manual fix
Fix: Medium
Context: Function
Tests: Update
CWE-89
CWE-564