August 22, 2026
βWe Donβt Use XMLβ β Yes You Do, and Itβs Reading Files
Whatβs up everyone! Nitin here π

By Nitin yadav
3 min read
XXE β XML External Entity injection β is a bug that lets you read files off the server, hit internal systems, and sometimes worse, all by feeding a crafted XML document to a parser that trusts too much. Everyone "knows" XXE, but almost nobody tests it, because they think "this app doesn't use XML." It does. It's hiding in file uploads, SOAP, SAML, and office documents. Let's find the XML nobody's looking at.
Why XXE happens
XML has a legacy feature called external entities β you can define an entity that pulls its value from an external source (a file, a URL) and reference it in the document. If the server's XML parser processes external entities (many old configs do by default), then an attacker who controls the XML can define
ENTITY xxe SYSTEM "file:///etc/passwdENTITY xxe SYSTEM "file:///etc/passwd{I cant add the full payload its triggering some issues in medium} and have the parser dutifully read that file and drop it into the output. That's the whole bug: the parser follows your instructions to fetch things it shouldn't.
Step 1: Find the XML entry points
This is where the bugs are, because these don't look like XML:
- Raw XML / SOAP APIs β obvious, but still under-tested
- SAML SSO β the SAMLResponse is XML (sensitive, high-value)
- RSS / sitemap / feed import
- SVG upload β SVG is XML; avatar/logo uploads are prime
- Office documents β
.docx,.xlsx,.pptxare ZIP archives full of XML; unzip, inject into a.xmlpart, rezip, upload - Any endpoint where you can flip
Content-Type: application/jsontoapplication/xmland it still parses
That last trick is gold: many APIs accept XML even when the client normally sends JSON. Change the content-type, send an XML body, and test.
Step 2: Classic in-band file read
If the parsed XML gets reflected back, use a basic external entity:
If the response contains the contents of /etc/passwd, you have in-band XXE. Swap in whatever field of the app's real XML schema gets echoed.
Step 3: No output? Go blind / OOB
When nothing reflects, exfiltrate out-of-band using an external DTD you host:
Your evil.dtd defines a parameter entity that reads a local file and sends it to your collaborator:
A hit on your server with the file contents in the query string confirms blind XXE. Even simpler as a first test: just point an entity at a collaborator URL to prove the parser makes outbound requests.
Step 4: Pivot to SSRF and beyond
External entities aren't limited to file://. Point them at internal HTTP:
Now XXE becomes SSRF β internal services, cloud metadata, the works. Depending on the parser and available protocols (expect://, jar://, PHP wrappers), XXE can even reach RCE, and a billion-laughs entity can cause DoS (don't fire that at a live target).
The impact ladder
- Parser makes an outbound request (blind, no file read) β medium
- Arbitrary file read (
/etc/passwd, config, source, keys) β high - XXE β SSRF β cloud metadata / internal services β high/critical
- XXE β RCE (rare, parser-dependent) β critical
Conclusion β the XXE playbook
- XXE = the parser follows your external entity to read files/URLs.
- Hunt hidden XML: SOAP, SAML, SVG upload,
.docx/.xlsx, or JSONβXML content-type swap. - In-band:
- Blind: external DTD + parameter entities β exfil to collaborator.
- Pivot to SSRF via
http://169.254.169.254/; escalate carefully.