Content Type Forcing – The XSS you may have missed.

~#: Introduction

It is pretty well known that some Cross Site Scripting vulnerabilities can be browser depended. For example in one of my past write ups, I covered a type of XSS that only worked on IE/Edge in a file upload functionality. However, not many people know that XSS can also be OS dependent. Content Type Forcing XSS is a prime example of that. Content Type Forcing is a technique that I was originally made aware by my good friend Rene Kroka (@rene_kroka). He found a research paper done by Cure53 that covered a lot of different browser security issues, and this attack vector really caught our attention. In essence this attack vector allows us to use endpoints with different Content Types such as json, pdf, mp4, mp3, and others to embed malicious JavaScript and force the browser to render it as HTML. The beauty about this attack vector is that it is fairly easy to identify and exploit. I highly recommend reading the research paper by Cure53 as well as some of the other publications by them.

~#: Hunting for Vulnerable Targets

The two most common types of endpoints that we were able to find, report, and get rewarded for, were APIs and file upload functionalities. The main aspect we need to look for when hunting for this vulnerability is the response headers. Although other headers may affect the exploitability of this bug, the main ones that will make the endpoint not vulnerable are:

  • X-Frame-Options: deny || same-origin
  • X-Content-Type-Options : no-sniff
  • Content-Disposition: attachment || inline

Vulnerable APIs Example

When looking for targets we first looked for APIs that allowed us to retrieve previously stored data using an API key in the URL parameter. For instance let’s say example.com/api/users?id=123&apikey=foobar allowed us to retrieve user data as long as our API key has the proper permissions. Upon requesting our own user data and noticing the above headers missing, we knew we could potentially turn the harmless JSON data into Stored XSS. This issue was found in dozens of public and private programs. We found that it was a common practice to not encode <> in JSON responses which allowed us to fairly easily achieve XSS. Here is an example of what a vulnerable API would look like:

Vulnerable File Uploads Example

Another common target we found were file uploads and file sharing functionalities. Hunting for this is fairly straight forward as well. As long as you can upload certain file types, then upon visiting the uploaded file URL it does not contain the headers mentioned above, it is probably vulnerable. One caveat we have found is that when uploading MP4s for example, some targets would compress our malicious file and get rid of our HTML/ XSS payload. Additionally, I do not know the full list of file types that this will work with. However we have tested and exploited the following: PDF, MP4, MP3. It should however be possible to do the same with other file types unknown to Internet Explorer.

Example vulnerable target:

~#: Exploiting the Bug

As briefly mentioned in the Introduction, this attack vector is OS dependent. It appears from our testing to affect users who currently use any Windows version prior to Windows 10 / Windows Server 2016. This of course generally decreases the impact of this bug since it not only requires victims to use IE 11, but also use an older operating system. The actual original research paper from cure53 describes Windows 10 IE/Edge as also being sometimes vulnerable to this, however during our testing we could not reproduce it. Maybe it is the case for older versions of Windows 10. Feel free to test this out, as it can likely lead to an increase of impact for this bug type. We will discuss more on impact. For sake of creating a proof of concept and testing, we can use a Windows 7 VM.

To actually exploit it, we will need to serve the vulnerable endpoint inside an iframe, which in turn will then force it’s content type to be the same as the parent document. Let us use Kali to create a simple PoC. Kali comes shipped with Apache which by default should let us host php pages. In Kali let’s create two files in the web server root:

evil.html

<iframe id=x src="evil.php"></iframe>
<script>x.location.reload()</script>

evil.php

<?php
header('location: http://example.com/jsonvuln.php?apiKey=12345')
?>

That’s it! That is all you need, the first evil.html file is simply an html page which will have an iframe pointing to our evil.php file. In turn the evil.php page will redirect to the vulnerable endpoint. Upon iframe reload the page response will actually be rendered as HTML, and JavaScript will execute in the context of the target.

The attack vector would then be to simply trick the target user to visit our malicious server, which then would execute JS in the context of the vulnerable site.

The above is an example of pointing our evil.php page to the previous json endpoint example. However, it would work the exact same way for PDF,MP4,MP3. Simply upload a file with embedded HTML/ XSS payloads in it’s data, and then point evil.php to it. Upon visiting our server, the browser will render the binary PDF/MP4 data as HTML and execute our payload.

~#: Impact

As previously mentioned, impact will generally be lower than a “regular” Stored XSS because of the exploit difficulty. Additionally, it is usually your job as the researcher to prove the impact of a successful exploitation. For example, whenever I tested file uploads for this vulnerability I always made sure before reporting that the files were not being hosted in some sandboxed content delivery domain. Another important point is that if you are going to hunt for this vulnerability in bug bounty programs, you should be sure that XSS vulnerabilities that only affects older browsers are in-scope. As I have seen programs that simply do not care if a vulnerability only affect certain browsers.

In conclusion, this was an interesting little bug type we started to hunt for. It was a big surprise for us to see how many targets were vulnerable to this, and also how few bug hunters know about this.

Here is an example report:

https://hackerone.com/reports/763812