Intro to XXE Injection
XML External Entity (XXE) Injection occurs when user-controlled XML input is parsed without proper sanitization, allowing an attacker to leverage XML features for malicious actions — from disclosing sensitive server files to shutting down the back-end. Ranked in OWASP’s Top 10.
XML primer
XML (Extensible Markup Language) is designed for flexible data storage and transfer, not display. Documents are element trees: one root element, with child elements nested inside.
Basic example:
<?xml version="1.0" encoding="UTF-8"?>
<email>
<date>01-01-2022</date>
<time>10:00 am UTC</time>
<sender>john@inlanefreight.com</sender>
<recipients>
<to>HR@inlanefreight.com</to>
<cc>
<to>billing@inlanefreight.com</to>
</cc>
</recipients>
<body>Hello, please share the invoice. Regards, John</body>
</email>
Key XML terms
| Term | Definition | Example |
|---|---|---|
| Tag | Keys of an XML document, wrapped with </> | <date> |
| Entity | XML variables, wrapped with &/; | < |
| Element | A tag and its stored value | <date>01-01-2022</date> |
| Attribute | Optional specifications inside a tag | version="1.0" |
| Declaration | First line, defines XML version/encoding | <?xml version="1.0" encoding="UTF-8"?> |
Reserved characters (<, >, &, ") must be written as entity references (<, >, &, ") when used as data. Comments: <!-- comment -->.
XML DTD
A Document Type Definition (DTD) validates an XML document against a pre-defined structure. It can be declared inline or in an external file.
Inline example:
<!DOCTYPE email [
<!ELEMENT email (date, time, sender, recipients, body)>
<!ELEMENT recipients (to, cc?)>
<!ELEMENT date (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
External file reference (using SYSTEM):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email SYSTEM "email.dtd">
External URL reference:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email SYSTEM "http://inlanefreight.com/email.dtd">
XML entities
Custom entities (variables) can be defined in a DTD with the ENTITY keyword:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
<!ENTITY company "Inlane Freight">
]>
Reference with &company; — the parser substitutes the value at parse time.
External entities — the XXE primitive
Entities can reference external files or URLs via the SYSTEM keyword:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
<!ENTITY company SYSTEM "http://localhost/company.txt">
<!ENTITY signature SYSTEM "file:///var/www/html/signature.txt">
]>
When the server parses this XML (e.g., in a SOAP API or web form), it fetches and substitutes the external resource. If the resolved value is returned in the response, an attacker referencing &signature; receives the contents of /var/www/html/signature.txt from the server’s filesystem.
This is the core mechanism behind XXE: external entity references that resolve to server-local files are returned to the attacker in the XML response.
Note: PUBLIC can be used instead of SYSTEM (typically for publicly declared standards), but SYSTEM covers most practical XXE cases.