🛡️SQL injection
String concatenation is the enemy
Injection wins when attacker-controlled text becomes syntax instead of data. One missing bind parameter turns a login query into a skeleton key, parameterized APIs exist to make the right thing ergonomic.
Vulnerable: interpolate user input
Never ship this
-- user supplies: ' OR '1'='1
SELECT * FROM users WHERE email = '' OR '1'='1';| risk |
|---|
| Returns all rows, authentication bypass |
Safe: bind parameters
Client protocol keeps data separate
-- driver sends text as parameter value, not parsed SQL
SELECT user_id FROM users WHERE email = $1;| email_param | user_id |
|---|---|
| ada@lab.example | 42 |
🧱Defense checklist
Layer defenses, parameterization is necessary but not sufficient.
| Defense | What it fixes |
|---|---|
| Prepared statements | Separates code from data at the protocol layer. |
| ORM parameterization | Same wins, if you never bypass it with raw strings. |
| Least privilege roles | Shrinks blast radius when a bug slips through. |
ORM safety is conditional
.raw, execute with concatenation, or dynamic ORDER BY as high-risk in review.Defense in depth
Beyond classic injection
Second-order injection stores malicious text now, executes later. Also watch ORM query gadgets and unsafe JSON operators, treat any path that reaches SQL as part of your attack surface.
TL;DR
SQL injection happens when untrusted input becomes part of SQL text instead of bound parameters, letting attackers alter statements ('; DROP … cliché or subtler data exfiltration). Defense: prepared statements/parameter binding everywhere, least-privilege DB users, input validation, and static analysis on dynamic SQL. Never concatenate secrets or user text into queries.