11.6 Injection Beyond SQL: LDAP, XPath, Code & Template Injection
Key Takeaways
- All injection flaws share one root cause: untrusted input is interpreted as part of a command, query or code rather than treated as data.
- LDAP injection manipulates directory filter syntax such as *)(uid=*) to bypass authentication or enumerate the directory.
- XPath injection abuses XML query syntax with payloads like ' or '1'='1 to bypass logic or extract nodes, and is not mitigated by database controls.
- Code and expression-language injection (eval, SpEL, OGNL, template engines) leads directly to remote code execution.
- The universal defence is parameterisation or context-aware escaping specific to the target interpreter, plus strict input validation.
11.6 Injection Beyond SQL: LDAP, XPath, Code & Template Injection
Section 12.2 and 12.3 cover SQL injection in depth. But syllabus item H10 lists the wider injection family — SQL injection, LDAP injection, code injection and XML injection — and asks for the potential implications of each and how these techniques benefit an attacker. SQL is only the most famous member of a class.
The unifying idea is worth stating once and remembering: an injection flaw exists whenever untrusted input crosses a boundary and is interpreted as part of a command, query or program rather than treated as inert data. Change the interpreter — a SQL engine, an LDAP directory, an XML query processor, a shell, a template engine — and you change the syntax of the attack, but not its nature or its defence.
1. LDAP Injection
LDAP (Lightweight Directory Access Protocol) queries directories such as Active Directory using a distinctive filter syntax built from parentheses and logical operators:
(&(objectClass=user)(uid=jsmith)(userPassword=secret))
When an application builds that filter by concatenating user input, an attacker manipulates the filter logic:
- Authentication bypass. A login that checks
(&(uid=<user>)(userPassword=<pass>))can be broken by submitting the username*)(uid=*))(|(uid=*or the classic*)(|(uid=*)), turning the filter into one that always matches. Supplyingadmin)(&)with any password can authenticate asadminwhere the password clause is neutralised. - Blind enumeration. By injecting wildcard and boolean conditions and observing whether results are returned, an attacker enumerates attributes character by character — the LDAP analogue of blind SQLi.
*)(uid=a*)versus*)(uid=b*)reveals which usernames exist.
The special characters that must be neutralised are ( ) * \ / NUL and the filter operators & |. The implication for the attacker is directory-wide: authentication bypass, disclosure of user attributes (including group memberships and sometimes password-related fields), and a map of the organisation's identity store.
2. XPath / XQuery Injection
XPath queries XML documents, and applications that store users or configuration in XML often authenticate against it:
/users/user[username/text()='jsmith' and password/text()='secret']
Because XPath has no equivalent of database privilege separation, XPath injection is in some ways more dangerous than SQLi: there is no notion of a low-privileged database account to contain it. Payloads mirror SQLi:
- Authentication bypass: username
' or '1'='1(oradmin' or '1'='1' or 'a'='a) makes the predicate always true. - Blind extraction: using
substring(),string-length()and boolean conditions to read the document node by node, exactly as boolean-blind SQLi reads a table. - Whole-document disclosure: injecting
//*style expressions to return every node.
The implication is disclosure of the entire XML data store and authentication bypass against any XML-backed login.
3. XML Injection (and its relation to XXE)
XML injection means inserting XML metacharacters (< > & ' ") or whole elements into an XML document the application builds, altering its structure. Two distinct outcomes:
- Structural/logic injection: adding an extra element to a message so that, say, a
<role>user</role>becomes<role>user</role><role>admin</role>and a naive parser honours the last one — privilege escalation via message tampering. This is the SOAP-injection idea from 10.5. - XXE (XML External Entity): covered in detail in 11.4 — injecting a DTD with an external entity to read local files, reach internal services (SSRF) or cause denial of service via entity expansion. XXE is the highest-impact member of the XML-injection family and the reason external-entity processing must be disabled.
4. Code and Expression-Language Injection
Code injection is the most severe class: untrusted input is passed to a function that executes it as program code, giving remote code execution directly.
- Interpreter
eval: PHPeval(),assert(),preg_replacewith the legacy/emodifier; Pythoneval()/exec(); JavaScripteval()andFunction(). Input reaching any of these runs as code. - Expression Language / template injection (SSTI): modern frameworks evaluate expressions in templates — Java SpEL and OGNL (the engine behind several catastrophic Apache Struts RCEs), Thymeleaf, Python Jinja2 (
{{7*7}}returning49is the canonical detection probe), Ruby ERB, and Node Pug/Handlebars. Server-Side Template Injection escalates from expression evaluation to full RCE ({{config.__class__...}}chains in Jinja2,#{...}in Thymeleaf). - Deserialization: untrusted serialized objects (Java, .NET, PHP, Python pickle) that instantiate attacker-chosen types on load — a distinct but related path to code execution.
Distinguish code injection (attacker input becomes code in the application's own language, run in-process) from OS command injection (11.4: input becomes arguments to a shell command). Both yield execution; code injection runs inside the interpreter, command injection spawns a shell.
The detection method for SSTI is the arithmetic probe: submit ${7*7}, {{7*7}}, #{7*7} and <%= 7*7 %> in turn and watch for 49 in the response, which tells you both that evaluation occurs and which engine is present.
5. The Shared Root Cause and the Shared Defence
Trusted structure + Untrusted input = Interpreter runs it
------------------------------------------------------------------------------
SQL query ' OR '1'='1 database command
LDAP filter *)(uid=* directory query
XPath expression ' or '1'='1 XML node selection
Shell command line ; rm -rf / OS command
Template / eval() {{7*7}} / system('id') arbitrary code
Because the cause is identical, the defence is identical in principle and only differs in mechanism per interpreter:
- Parameterisation / separation of code and data wherever the interpreter supports it — parameterised SQL queries, LDAP APIs that bind values rather than concatenate filters, XPath variable binding, sandboxed template contexts that never evaluate user input as an expression, and never passing user input to
eval. - Context-aware escaping as a secondary control — escape exactly the metacharacters of the target interpreter (LDAP
()*\, XML<>&'", shell metacharacters), not a generic set. - Strict input validation — allow-list the expected format (a numeric ID is digits only), which shrinks the payload space for every class at once.
- Least privilege — the LDAP bind account, database account and application process should hold only the rights they need, so a successful injection is contained.
For the exam, the key takeaways are that injection is one class with many dialects, that each dialect has a recognisable payload signature, that code/template injection means RCE while LDAP/XPath typically mean authentication bypass and data disclosure, and that parameterisation — not blacklisting — is the real fix in every case.
An application authenticates users with the LDAP filter (&(uid=<input>)(userPassword=<input>)). An attacker submits the username 'admin)(&)' with an arbitrary password. What class of attack is this and what is the intended effect?
Why can XPath injection be considered, in one respect, more dangerous than SQL injection?
An assessor submits {{7*7}} into an input field and the response renders 49. What has been detected and what is the typical escalation?
What single principle most reliably prevents the entire injection family — SQL, LDAP, XPath, XML and code injection?