The oldest and still most common vulnerability class. All injection attacks share one root cause.
The root cause
Your backend speaks many languages: SQL, HTML/CSS/JS, shell. Each language has special characters that separate code from data.
- Trusted program
Application code selects the intended statement or operation.
- Untrusted value
User input belongs in a value channel.
- Injection
Concatenating input into executable syntax lets data change the operation.
Keep the statement structure fixed and provide external values through a data channel.
How to read this model
A program die and a separate value feed. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
When you concatenate user input directly into a query or command, you trust that the input has no special characters. That trust is the vulnerability.
SQL injection
The setup
A login page sends email and password. The server builds a query by string concatenation:
SELECT * FROM users WHERE email = '<user input>'
The happy path
User enters alice@gmail.com:
SELECT * FROM users WHERE email = 'alice@gmail.com'
Returns Alice. Correct.
The attack
Attacker enters: ' OR '1'='1' --
- Payload
The attacker supplies an apostrophe followed by OR with the always-true comparison '1'='1', then a SQL comment marker.
- Altered statement
The first quote ends the intended value. OR changes the WHERE logic; the comment can remove the remaining constraint.
- Exposure
The demonstrated vulnerable query returns all matching rows rather than just the intended user. Parameterize it.
The example payload changes query logic when concatenated into SQL.
How to read this model
An open text press with an uncontrolled syntax feed. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
What happened:
- The first
'closes the string. OR '1'='1'is always true.--comments out the rest, hiding the stray closing quote.
Result: the attacker gets every user without knowing any email.
Worse: data destruction
The same trick can run a second statement:
SELECT * FROM users WHERE email = ''; DROP TABLE users; --
The ; ends the first statement. DROP TABLE users deletes the whole table.
The fix: parameterized queries
Separate the query from the data. Send two things: the statement, and the values.
- Statement
Use a fixed statement such as WHERE email = $1.
- Bound value
Bind the entire malicious-looking input as one string value.
- Database
The database compares the value as data. The example finds no matching email; the payload does not become SQL syntax.
Parameterization preserves the distinction between SQL code and data.
How to read this model
A fixed statement die beside an isolated value holder. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
The database puts the value into the $1 slot as pure data. It is never interpreted as code. The malicious input becomes a garbage string that matches no email.
# Wrong: string concatenation
cursor.execute("SELECT * FROM users WHERE email = '" + email + "'")
# Right: parameterized
cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
Second line of defense: least-privilege DB user
Parameterized queries are the real fix. But add a second layer so a slip is still harmless:
NoSQL injection
You're not safe just because you don't write SQL. MongoDB queries are JSON objects, and objects can contain operators:
{ "email": "alice@gmail.com" } // normal
{ "email": { "$ne": "" } } // attacker-controlled: matches everything
If your app passes raw user JSON into a query, an attacker can inject $ne (not equal), $gt (greater than), $exists, and more. Never pass raw user JSON straight to the database: validate the shape first.
Command injection
The same confusion, but the target is the operating system, not the database.
The setup
A user uploads an image. Your server calls a CLI tool to resize it:
ffmpeg -i input.jpg -h 120 -w 220 -o <user filename>
The attack
Attacker passes: ; rm -rf /
- Intended operation
The example intends to invoke ffmpeg with input and output arguments.
- Injected separator
A semicolon in a concatenated shell command can begin a second command, illustrated by rm -rf /.
- Safe process API
Pass arguments separately without a shell, and validate application-specific path and option constraints.
Avoid handing untrusted input to a shell interpreter.
How to read this model
An argument inspection fixture beside a guarded process control. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
The ; ends the first command. rm -rf / runs next. Attackers can also use | (pipes) or & (background) for more creative damage.
The fix: argument arrays
Separate the command from its arguments. Pass arguments directly to the process, not through the shell:
// Wrong: shell interprets the input
exec("ffmpeg -i input.jpg -o " + filename)
// Right: arguments go straight to the process
spawn("ffmpeg", ["-i", "input.jpg", "-o", filename])
The argument is passed as a plain string; the shell never interprets it.
Summary: the mental model
| Context | You speak | Fix |
|---|---|---|
| Database | SQL / NoSQL query | Parameterized queries, validate shape |
| Operating system | shell command | Argument arrays |
| Browser | HTML / JS | Sanitize, CSP (see xss and csrf) |
Terms: GLOSSARY · Related: database · Next: authentication · Up: security mindset