SQL Injection (SQLi)
- Attacker injects SQL into inputs concatenated into a query
- Goal: read data, bypass auth, modify/drop data
# Vulnerable
query = f"SELECT * FROM users WHERE email = '{email}'"
# Input: [email protected]' -- → password check commented out
Kinds
In-band— result in the HTTP response (UNION SELECT)Blind— no output; infer viaBoolean: page differs onAND 1=1vsAND 1=2Time:SLEEP(5)delays response when trueOut-of-band— exfiltrate via DNS/HTTPSecond-order— input stored, triggers later in a different query
Prevention
-
Parameterized queries — the only reliable fix
cur.execute("SELECT * FROM users WHERE email = %s", (email,)) -
ORMs (SQLAlchemy, Django, Prisma) — parameterized by default; still vulnerable on
raw()/text()with concatenation - Allowlist identifiers — column/table names can't be parameterized
- Least privilege DB user — no
DROP, noSUPERUSER - WAF — defense in depth only; bypassable
Don't rely on
- Escaping — easy to get wrong
- Input validation —
a'[email protected]is a valid email string - Hiding error messages — blind SQLi still works