← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

SQL Injection

security CWE-89 OWASP A3:2021 CVSS 9.8 PHP 5.1+ Intermediate

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)

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();

Added 13 Mar 2026
Edited 22 Mar 2026
Views 36
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 2 pings S 1 ping S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 1 ping T 0 pings W 1 ping T
No pings yesterday
Perplexity 10 Amazonbot 9 Ahrefs 5 Google 2 Qwen 1
crawler 26 crawler_json 1
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

✓ schema.org compliant