Glossary
What is SQL injection (SQLi) — when input rewrites your database's commands
SQL injection (SQLi) is when user input rewrites the meaning of a database query (SQL), leading to reading, altering, or wiping data. How it works, and the real defense (placeholders / prepared statements, ORMs, least-privilege DB users) — explained defensively, without attack steps.
"The text you typed into a search box becomes 'part of a command' to the database" — that's SQL injection. Here's how it works and how to reliably prevent it (no attack steps).
Why it happens (the mechanism)
The root cause is building SQL by string concatenation. Mix input straight into the statement and it can cross the "value boundary" and act as command.
✗ String concatenation (dangerous)
Input concatenated into the statement → input can be read as part of the command
✓ Placeholders (safe)
Values passed into ? / $1 slots as data → always stay values
The damage is "everything that DB connection can do." If the internal DB is reachable, it's a classic entry to mass leaks, alongside RCE and SSRF.
Defense
Use placeholders / prepared statements (most important)
Don't build SQL by concatenation. Pass values via ? / named parameters as 'data'. This alone nearly eliminates the whole class.
Lean on your ORM / query builder
Most ORMs use placeholders by default. The less raw SQL you hand-write, the safer. If you must write raw SQL, always parameterize it.
Least-privilege DB user
Don't grant the app's DB user unneeded rights (DROP, other tables, admin ops). Even if breached, contain the damage.
Input validation as a supplement
Type/length/format checks help, but don't make them your primary defense — they sit on top of placeholders.
ITD's view: stop hand-building raw SQL in the first place
SQLi has existed forever yet won't die — because it's "convenient" to mix input into the statement. ITD's stance is plain: never create a place where values are string-concatenated into SQL. Make placeholders or an ORM the default and this vulnerability vanishes by design. Don't go down the "try harder at manual escaping" road.
A blind spot: placeholders only carry 'values'
Placeholders aren't a cure-all. They carry values only — not query structure like table names, column names, or the ORDER BY direction (asc/desc).
When you need those dynamic (e.g. letting a user pick a "sort key" or "filter column"), don't drop input into SQL — select the real name from a predefined allowlist instead. "Sort column" and "filter column" are the classic blind spots where people assume placeholders have them covered.
Read next
- Glossary: What is RCE · What is XSS
- Basics: Security basics
FAQ
QWhat happens with SQL injection?
An attacker changes the meaning of a database query — reading data that should be hidden, altering it, or at worst wiping everything or bypassing authentication. It's a classic cause of mass data leaks.
QWhat's the most reliable defense?
Pass values via placeholders (prepared statements). Don't build SQL with string concatenation; pass values as 'data' through a separate channel so input can never be read as command. Most ORMs do this by default.
QIs escaping input enough?
Manual escaping is error-prone and discouraged. Use placeholders. Also give the DB user least privilege to shrink the blast radius if something gets through.