Injection: the category a request filter reaches most directly

Injection attacks happen when an application passes input to an interpreter, such as a database, a shell or a browser, and the interpreter runs part of that input as a command. It is A05 in the OWASP Top 10:2025. Because the attack travels inside the request, this is the category where a request filter does the most, and the fix still belongs in the code.

Section Rules Updated OWASP A05:2025

Quick facts

Category
A05:2025 Injection, down from third place in 2021
Mapped weaknesses
37 CWEs, among them CWE-89 SQL injection, CWE-79 cross-site scripting and CWE-78 OS command injection
Known vulnerabilities
62,445 CVEs in OWASP's data; cross-site scripting accounts for more than 30,000 and SQL injection for more than 14,000
Interpreters named
SQL, NoSQL, OS command, ORM, LDAP, and expression languages such as EL or OGNL
Does a WAF stop it?
Mostly. The payload is in the request and has a recognisable shape; the vulnerable query stays in the code until it is fixed

Figures are from the A05:2025 page of the OWASP Top 10.

What the category covers

OWASP lists four ways an application becomes injectable.

  • Input is not validated, filtered or sanitised. Whatever arrives is passed on as it came.
  • Queries are built by joining strings. Dynamic queries or non-parameterised calls reach the interpreter without escaping for its context.
  • ORM search parameters take raw input. The input widens a query until it returns records it should not.
  • Hostile data becomes part of a command. It is concatenated into a query, a shell command or a stored procedure.

The interpreter differs from case to case. The mistake underneath is the same: data and instructions travel in one string, and the interpreter cannot tell where one ends.

LDAP, XPath, template and HTML injection

The same mistake appears wherever input reaches an interpreter. LDAP injection (CWE-90) changes a directory query; XPath injection (CWE-643) changes a query against an XML document; expression language injection (CWE-917) runs input inside a template or framework expression. Line breaks in header values, CRLF injection (CWE-93), are the same pattern aimed at HTTP itself.

HTML injection is the mildest form of cross-site scripting: the input is rendered as markup without running a script, which is enough to fake a form or a message on a trusted page. In each case the fix is the one above: keep data out of the instruction channel.

What it looks like in a request

An injection attempt has to put interpreter syntax where data was expected. That syntax is visible to anything that reads the request.

The OWASP page gives a SQL example: an account lookup built by joining strings receives ' OR '1'='1 as the account number, and the query returns every account. A shell example, the subject of command injection, appends ; cat /etc/passwd to a hostname that the application passes to a lookup command. In both cases, the request carries quote marks, operators or command separators in a field that should hold an identifier or a name.

Cross-site scripting is the same pattern aimed at a browser: markup or script arrives in a field and is later sent back to other visitors without encoding.

WHAT A FILTER HAS TO WORK WITH SYNTAX IN THE REQUEST KNOWN PATTERN FIXED ONLY IN THE CODE SQL INJECTION OS COMMAND INJECTION CROSS-SITE SCRIPTING ORM OR NOSQL QUERY ABUSE INJECTION IN A CUSTOM FORMAT // every row ends in the code column
// five kinds of injection: syntax in the request, a known pattern, a fix in the code

What a request filter can and cannot do

A filter matches the shape of a payload. That works well where the shape is distinctive and common, which is why SQL injection and cross-site scripting are the classic examples of what rule sets describe.

  • It can refuse a known payload before it reaches the code. That protects an injectable query while the fix is written, which is virtual patching.
  • It cannot tell a payload from legitimate text that looks like one. A support ticket quoting SQL, or a forum post about markup, matches the same patterns, which is where false positives on this category come from.
  • It cannot see injection that uses no recognisable syntax. A custom query language, an encoding the rules do not decode, or a payload split across fields can pass.
  • It does not make the query safe. The interpreter still treats data as instructions, and the next variation of the payload can still reach it.

Watching matches in monitor mode before enforcing shows which of your own fields carry text that looks like code.

What fixes it

The OWASP guidance is ordered by how well each measure works.

  1. Keep data out of the interpreter. Use a safe API with a parameterised interface, or an ORM; stored procedures can still be injectable if they join strings.
  2. Validate input on the server. Positive validation against what a field may contain helps, and OWASP notes it is not a complete defence.
  3. Escape what remains, for the specific interpreter. Escaping is error-prone, and table or column names cannot be escaped at all.

For cross-site scripting, the equivalent is encoding output for the context it lands in: the browser has to receive text as text.

Rules that describe it

In the OWASP Core Rule Set, this category maps to several rule files: REQUEST-942 for SQL injection, REQUEST-941 for cross-site scripting, REQUEST-932 for remote command execution, and REQUEST-934 for generic attacks. Each rule adds to a request's score, and the score decides.

File numbers are stable across CRS 4 releases; the rules inside them change with each release.

Questions

Can a WAF stop SQL injection?

Mostly. A WAF can match the syntax that SQL injection has to place in a request and refuse it before it reaches the database. The injectable query stays in the code, so a payload the rules do not describe can still work until the query is parameterised.

Is cross-site scripting part of injection?

Yes. In the OWASP Top 10:2025, cross-site scripting (CWE-79) is mapped to A05 Injection, alongside SQL, command and other interpreter injection.

Why does a WAF block text that mentions SQL?

Because a pattern for an injection payload also matches legitimate text that contains the same syntax, such as a support ticket quoting a query. Those are false positives, fixed with a narrow exception for the field where it happens.

What is the real fix for injection?

Parameterised queries or a safe API that keeps data out of the interpreter, then server-side validation, then context-specific escaping for what remains.