PortSwigger's "Web shell upload via Content-Type restriction bypass" Walkthrough
This is the next of PortSwigger’s file upload labs. This one is only slightly more difficult because of a Content-Type check being performed by the server.
You’ll need Burp Suite set up before following this walkthrough. You’ll also need a Portswigger Academy account. Once logged into your account, view the lab at https://portswigger.net/web-security/file-upload/lab-file-upload-web-shell-upload-via-content-type-restriction-bypass
. This is accessible from the “all labs” view or from the File Upload page.
Challenge Information

Click the “Access the Lab” button and you will be taken to a temporary website that is created for your account. This will be in format https://<random string here>.web-security-academy.net/
.
As before, we’ll to upload a PHP script as our avatar. This PHP code will execute once visited in a browser, allowing us to exfiltrate the contents of /home/carlos/secret
.
Here’s the website:

If we login with provided credentials wiener:peter
, we can upload avatar photos via the /my-account
view:

Lab Solution
Open a text editor and save the following contents in a file named webshell.php
:
<?php echo file_get_contents('/home/carlos/secret'); ?>
Then try to upload the file:

It says that we’re restricted to two allowed Content-Types
. These are image/jpeg
and image/png
. We uploaded one that’s text/php
.
In Burp Suite, find the request in Proxy > HTTP proxy
, right-click it, and then Send to Repeater
.

The request defines the Content-Types
in the form data. We can change the value for our web shell to image/jpeg
.

Click send, and see that it was successful.

In your browser, reload the /my-account
page and then right-click the broken avatar image (broken because it’s not a real image file), and open in a new tab:

This new tab is the PHP file we uploaded, which will execute to get the file contents and then echo them as output.

Take this value (GCHjG786pKA2IND9uMO3M4grtctSChaB
) and submit it:

The lab is now solved!
