Unrestricted File Upload

Level: Practitioner

Today we will solve Portswigger’s “Web shell upload via extension blacklist bypass” lab from their file upload vulnerability series.

This is the information that we have before starting:

This lab contains a vulnerable image upload function. Certain file extensions are blacklisted, but this defense can be bypassed due to a fundamental flaw in the configuration of this blacklist. To solve the lab, upload a basic PHP web shell, then use it to exfiltrate the contents of the file /home/carlos/secret. Submit this secret using the button provided in the lab banner. You can log in to your own account using the following credentials: wiener:peter

Okay, let’s go! Also, don’t forget to run Burp, we will need that very soon.

First, let’s log in with the credentials wiener:peter. On the “My account” page we can see a place for uploading an avatar. Since we’re doing a file upload vulnerability lab, then this is where the magic happens!

As our goal is to get the contents of the file /home/carlos/secret, let’s create a basic PHP web shell that allows us to do just that, such as:

<?php echo file_get_contents('/home/carlos/secret'); ?>

You can name it whatever you want, I went with shelly.php. Let’s try to upload it and see what happens. This is the response that we get:

Let’s head on to Burp, check HTTP history and find the request that was used to attempt to upload the file - that would be POST /my-account/avatar. When we take a look at the response to this request, we can see that we are dealing with an Apache server. Let’s forward the request to Repeater.

Apache uses a configuration file called .htaccess which provides a way to make configuration changes on a per-directory basis. The Apache HTTP server tutorial recommends avoiding the use of .htaccess files and brings out security as one of the reasons for that. “You are permitting users to modify server configuration,” it says. “It may result in changes over which you have no control,” it says. Sounds perfect, let’s try to exploit that!

Let’s try to smuggle in our PHP web shell with a different extension. What we are going to do is tell the .htaccess file that we want to add a file extension (an arbitrary one, I used .lol) that would be run as PHP - it means that the extension should be associated with the MIME type application/x-httpd-php.

So we need to make three changes to the Burp request:

  1. Change the value of the filename parameter from shelly.php to .htaccess.

  2. Change the value of the Content-Type header from application/octet-stream to text/plain.

  3. Replace the contents of our shell with the following Apache directive:

     AddType application/x-httpd-php .lol
    

This is what it looks like:

When we send the request, the file is uploaded successfully. Now let’s try out the new extension!

Let’s go back to the original POST /my-account/avatar request. Everything else remains the same, we only need to change the file extension, so our file name goes from shelly.php to shelly.lol, and we are able to upload it with the following response:

When we go back to the “My account” page with Burp running, then Burp’s HTTP history reveals us the location of the webshell which is /files/avatars/shelly.lol

Now let’s check the response to this request and there we can see the contents of /home/carlos/secret that we needed to solve the lab. Hooray!