03-04-2019 / From 0 to pentesting hero

Reflected File Download

In one of the previous episodes, I demonstrated CSV injection - that is, the ability to execute external code in an app that opens CSV files.

The use of such attack is then restricted to several programs. Can you expand the potential attack vector for a larger number of applications?

In today's episode of "from 0 to pentesting hero" about Reflected File Download.

This type of vulnerability usually occurs in jsonp endpoints.

What is jsonp?

JSONP

Suppose we have an API that returns the current time.

<?php
header('Content-Type: application/json');
header("Content-Disposition: attachment");
echo json_encode(array('time' => time()));

We want to download this data using JavaScript.

If the API is within the current domain, everything is fine.

<script  src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script>
$.ajax({
	url: "http://another_domain.example/od0dopentestera/api.php"
	}).done(function(data) {
		alert(data.time);
	});
</script>

The problem arises, however, if this API belongs to an external service.

By default, the browsers do not allow to send an ajax request to another domain.

The protection here is the Same Origin Policy.

Same Origin Policy

One solution to this problem is JSONP.

The workaround uses the fact that unless you can send ajax requests to an external domain, you can use the {% raw %}<script>{% endraw %} tag to load external JavaScript code.

A lot of websites work this way - when various libraries are hosted on external servers of service providers - that is CDNs.

<script  src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script>
function test(dane) {
	alert(dane.time);
}
</script>
<script src="http://another_domain.example/od0dopentestera/api.php?callback=test"></script>

However, we can't load the file in json format - because it will not be recognized by the browser as a valid javascript code.

But if the contents of the json file are wrapped in a function call - the javascript interpreter will understand this as the instructions for executing a given function and json will be passed there as a parameter.

Let's see this in practice. The API returns the result wrapped in the function name that was given as the callback parameter.

API JSONP

On our site, we enclose this API call in the script tag. Thanks to this API data will be passed to the JavaScript function we choose.

API call

Most developers do not validate the function name - this makes the endpoint vulnerable to today's attack.

In the CSV injection attack, we gave the function, starting from the equality sign.

This time we will use the bat format - the commands can be separated using a pipe.

If we give the name of the command as a callback, followed by the pipe and then we write the whole file with bat extension, Windows will think that it is dealing with a bat batch program.

Example BAT program

It will execute the given command and then the rest of the file.

The only thing that stands in our way is the name of the file - currently it is downloaded as json.

What comes to help is the download attribute, which we can pass to the href tag.

Thanks to this, the file will be downloaded as .bat.

Download .bat file

Now everything we need is an unaware user that will execute such file.

It is worth remembering that the effectiveness of such attack largely depends on the domain from which the file is downloaded.

For example, a standard user will be more likely to open a file downloaded from the bank's website - because it is the entity that we trust.

Bank

In this example, I used bat files and Windows. However, nothing stands in the way of a similar attack on .sh files under Linux1.

Attack Linux .sh files

How to protect yourself against this attack? Set the Content-Disposition header with the defined file name and allow only defined callback names.

Content-Disposition: attachment; filename="file.png"

And that's all in this episode. Now you know that even downloading files can be dangerous.