📋 What Is It?
Injection occurs when untrusted data from an API request is sent to a downstream interpreter as part of a command or query, and the interpreter cannot tell the attacker's data apart from the developer's instructions. The root cause is always the same shape: a string or object built from request input is interpreted rather than treated as inert data. The interpreter changes - SQL engine, MongoDB query planner, OS shell, LDAP directory, XPath parser, log sink - but the mechanism does not.
APIs sharpen the problem: they accept structured input, so an attacker can inject whole objects ({"$ne": null}), they expose client-driven sort/filter/fields semantics, they are machine-to-machine so hostile input is never filtered by a browser, and a single endpoint may chain to several interpreters at once.
⚠️ Common Exploits
- SQL Injection: concatenated
WHEREclauses, dynamicORDER BY - NoSQL Injection: a string field arriving as an operator object
- Command Injection: request values spliced into a shell string
- LDAP / XPath Injection: filters built by concatenation
- Template & Expression Injection: user text rendered as a template
- Header & Log Injection: CRLF and forged log lines
- ORM Escape Hatches: raw-SQL helpers reached with unbound input
🔴 Attack Flow
↓
2. Probe with metacharacters and operator objects (
', ;, {"$ne":null})↓
3. Watch for errors, timing changes, or altered result sets
↓
4. Shape a payload for the interpreter that answered
↓
5. IMPACT: Auth bypass, whole-table exfiltration, or command execution!
❌ Vulnerable Code
✅ Secure Code
✓ Prevention Checklist
- Use parameterised queries or a safe ORM binding for every interpreter
- Validate input against a strict schema - type, shape, length, and range
- Reject objects where a scalar is expected (the NoSQL operator trick)
- Allow-list identifiers: table, column, sort field, file path, command
- Never build shell strings; pass argument arrays with
shell=False - Escape or avoid concatenation in LDAP, XPath, and template contexts
- Encode output for the sink it is heading into
- Grant the database account the least privilege it needs
- Audit ORM raw-query escape hatches in code review and with SAST
- Log and alert on rejected input patterns rather than silently dropping them
🔍 Detection & Tools
Testing:
Code & Runtime:
How to Test:
- Fuzz every parameter with quotes, semicolons, and comment markers
- Send an operator object where a string is expected
- Look for timing differences (
SLEEP,pg_sleep) on blind paths - Test
sort,filter, andfieldsparameters specifically - Grep the codebase for string-built queries and
shell=True
🌍 Real-World
These are documented incident classes - recurring patterns rather than single CVEs.
- Login bypass via NoSQL operators: a JSON body sends
{"$ne": null}where a password string was expected and authenticates without a credential. - Mass exfiltration through SQLi: one concatenated filter parameter dumps entire tables via
UNIONor blind extraction. - Command injection in media pipelines: filenames or conversion options passed to a shell allow arbitrary commands on the worker.
- Template injection in "customisable" APIs: user-supplied templates rendered server-side lead to remote code execution.
- ORM escape hatches: a single
raw()/literal()call with unbound input reintroduces SQLi into an otherwise safe codebase.
📌 Quick Tips
- DO NOT concatenate input into any query or command
- DO NOT assume a JSON field is the type you declared
- DO bind parameters and validate with a schema
- DO allow-list identifiers and sort fields
- DO run the database as a least-privilege user
📜 Compliance
Related Standards:
- OWASP API Security Top 10 2019 - API8
- 2023 note Injection was folded into API8:2023 Security Misconfiguration & general secure-coding guidance
- CWE-89 SQL Injection
- CWE-943 Improper Neutralization in Data Query Logic (NoSQL)
- CWE-78 OS Command Injection
- CWE-1336 Server-Side Template Injection