In this guide, I’m going to show you one method to consider when you come across a file upload that only accepts PNG files. This method could theoretically be used for other file-types as well, but I’ll demonstrate uploading a PHP file on a file upload feature that “should” only allow PNG files on Popcorn from Hack The Box.
Note: This post does not intend to serve as a walkthrough or write-up for Popcorn at HackTheBox.
Table of Contents
- Setting the Stage
- Getting Malicious and Performing the Bypass
- Using the Webshell
- Closing Thoughts
Setting the Stage
Before diving in, let’s talk about where the vulnerable functionality exists. Popcorn is running an application called Torrent Hoster that allows for us to upload our own torrent files. This upload functionality is found at the following URL.
http://10.10.10.6/torrent/torrents.php?mode=upload

To give it a test upload, we’ll download a torrent for a Kali image from https://www.kali.org/downloads/ and upload that here.

Once the torrent file is saved, we’ll upload it to Torrent Hoster.

Once the torrent is uploaded, we’re taken to a page that shows us the default ‘No Screenshot’ image.

For fun, we’ll click Edit this torrent and upload our own image as a PNG file.

So here’s the thing. So far, we’ve found two file upload features on this web application. The first was to upload a .TORRENT file, and the second was to upload a .PNG file as a screenshot of the torrent. This is great, but how can this be exploited? Well to start, the Wappalyzer Firefox extension shows us that Popcorn is running PHP. What if instead of uploading a .TORRENT or .PNG, we tried to upload a .PHP webshell? Could we gain code execution?

Uploading a file is only any good if we’re able to execute the contents once its uploaded. Luckily for us, the uploaded PNG files are accessible externally from the following address.
http://10.10.10.6/torrent/upload/

Since we have a way to execute the uploaded PNG files, we’ll target this file upload as our exploitation path. To see if PHP files are even allowed without any bypass technique, let’s create a quick example PHP that we can attempt to upload. To create the PHP file, I just used the following command.
echo 'hello world' > test.php
Trying to upload test.php immediately returns an error.

So how do we bypass this and get our PHP uploaded?
Getting Malicious and Performing the Bypass
Let’s start by creating a malicious PHP file that we actually want to upload, since our test.php isn’t really going to do us any good. I like to use this PHP webshell one-liner to create webshell.php.
<?php system($_GET['cmd']); ?>
With this file created, let’s spin up BurpSuite and route our traffic through it. With Burp running, I’m going to attempt to upload webshell.php so we can look at the request.

Obviously this will fail to upload as well, just like the previous PHP file failed to upload. While we’re here, let’s leave Burp running and upload a valid PNG file again so we can compare the two requests within BurpSuite and spot the difference.

Within the Burp proxy HTTP History tab, we’re able to see both requests.

At this time, we’re not sure what checks the web application is performing to verify PNG uploads. It would be simple enough to try a bypass that just changes the filename of “webshell.php” to “webshell.png.php”, so lets send our PHP request to Repeater and see what happens when we make this simple modification.
Content-Disposition: form-data; name="file"; filename="webshell.png.php"
Content-Type: application/x-php
<?php system($_GET['cmd']); ?>

That didn’t work. Alright, so we need to do something more. In addition to the above change, let’s also adjust the Content-Type to match what the valid PNG file had.
Content-Disposition: form-data; name="file"; filename="webshell.png.php"
Content-Type: image/jpeg

Nice! Looks like we got that to work out. But what if it didn’t? We could take this even further by extracting the “Magic Bytes” from the actual PNG upload, and pasting them before the beginning of our PHP script. An example of that would look like this.

Using the Webshell
Now that we have our malicous PHP file planted, we can navigate to the following URL and figure out what name it was assigned.
http://10.10.10.6/torrent/upload/

On this page, let’s browse to the PHP file and add a parameter called cmd that contains a value of the command we wish to execute.
http://10.10.10.6/torrent/upload/file.php?cmd=whoami

Nice! We have command execution.
Closing Thoughts
File uploads are one of the most difficult exploitation paths to harden, which make for great targets for hackers. When presented with a file upload that only accepts certain file extensions, such as PNG, always try the following:
- Appending the name of the file extension in the filename parameter.
- Adjusting the content-type to match that of an accepted file-type.
- Include magic bytes for an accepted file.
We were able to leverage Popcorn on Hack the Box to demonstrate these techniques. I hope you found this guide informational, and if so, please feel free to check out some of my other publications.