Injection
OWASP Top 10
Course 1 · Chapter 3 · A03: Injection
If you've done the SQL-injection and XSS courses, this chapter is a homecoming: A03 Injection is the family those two belong to. It's the one category where you've already gone deep twice — so here we zoom out to see the whole family, the single root cause they share, and the unified defence, then point you back to the depth.
A03: Injection — Once #1, Now #3
Injection sat at #1 for years and dropped to #3 in 2021 — and that movement tells a story. It didn't get less dangerous; rather, frameworks made the safe path the default (ORMs parameterize, template engines auto-escape), so the rate of injection fell. The 2021 category also absorbed Cross-Site Scripting (XSS), which used to be its own entry — formally recognizing that XSS is just injection aimed at the browser. So A03 now spans the whole family.
The One Root Cause
The Members of the Family
| Injection type | Interpreter | Breakout / example | Deep-dive |
|---|---|---|---|
| SQL injection | SQL database | ' OR '1'='1 | SQLi course |
| Cross-Site Scripting (XSS) | the browser | <script>…</script> | XSS course |
| OS command injection | the OS shell | ; rm -rf / / && curl evil | this chapter |
| LDAP injection | an LDAP directory | *)(uid=* filter manipulation | this chapter |
| NoSQL injection | a document DB | {"$ne": null} operator injection | SQLi Ch. 9 |
| Template injection (SSTI) | a template engine | {{7*7}} → 49 | this chapter |
The One You Haven't Covered: OS Command Injection
Since SQLi and XSS have their own courses, the family member worth a closer look here is command injection — when untrusted input reaches an OS shell command. It's especially dangerous because it can mean full server compromise (remote code execution), not just data access:
Notice the fix is structurally identical to parameterized SQL queries: separate the command from the data. Passing arguments as an array (rather than building one shell string) means the input can never become shell syntax — the same "keep data off the code channel" principle, in a different interpreter.
Spot-the-Pattern: SSTI
Server-Side Template Injection is a modern family member worth recognizing: if untrusted input is rendered as a template (not just into one), the template engine evaluates it. The classic probe is {{7*7}} — if the page returns 49, the input is being evaluated as template code, which often escalates to remote code execution. The cause is the same (input treated as code); the fix is to never render user input as a template — pass it as data to a fixed template instead.
The Unified Defence
Because all injection shares one root cause, the defences rhyme across the family — and they're exactly what the SQLi and XSS courses taught:
| Interpreter | Keep-data-as-data defence |
|---|---|
| SQL | parameterized queries / prepared statements |
| Browser (XSS) | context-aware output encoding (+ CSP) |
| OS shell | avoid the shell; pass args as an array (execFile) |
| LDAP / NoSQL | parameterized/safe APIs; validate types & escape filter metachars |
| Templates | never render user input as a template; pass it as data |
Hands-On Exercises
For each, name the injection type, the interpreter, and the unified defence: (a) ' UNION SELECT … in a search box; (b) <img src=x onerror=…> in a comment; (c) ; cat /etc/passwd in a hostname field; (d) {{7*7}} returning 49. State the one root cause they all share.
Given exec("ping -c 1 " + req.query.host), show how an attacker achieves command execution and why it can mean full server compromise. Write the safe version and explain why it's the same principle as parameterized SQL queries.
Explain why A03 moved from #1 to #3 and absorbed XSS, and why that doesn't mean injection is "solved." Then state the one principle unifying SQL, XSS, command, LDAP, NoSQL, and template injection, and give the keep-data-as-data defence for three of them.
📄 View solutionChapter 3 Quick Reference
- A03 Injection — once #1, now #3 (frameworks made safe defaults common); 2021 absorbed XSS as injection-into-the-browser
- One root cause: untrusted input parsed as code instead of staying data — same bug across the whole family
- Family: SQLi (DB), XSS (browser), OS command (shell), LDAP, NoSQL (operators), template/SSTI
- Command injection — input into a shell (
; rm -rf /) → can be full RCE; fix: avoid the shell, pass args as an array (execFile) - SSTI — rendering input as a template (
{{7*7}}→49) → often RCE; fix: pass input as data to a fixed template - Unified defence: keep data off the code channel — parameterized queries (SQL) · output encoding+CSP (XSS) · arg arrays (shell) · safe APIs/type-validation (LDAP/NoSQL) · data-not-template (SSTI)
- Plus defence in depth: allowlist validation, least privilege, avoid dangerous sinks
- Deep-dives: SQLi course, XSS course (+ SQLi Ch. 9 for NoSQL)
- Next chapter: A04 Insecure Design — flaws no code fix solves; threat modeling & secure-by-design