In this post, we are going to solve the PortSwigger lab: “Remote code execution via polyglot web shell upload”.

To solve the lab, we need to upload a PHP file that reads and displays the content of the /home/carlos/secret file. To demonstrate that we have completed the lab, we must submit the content of this file.
Additionally, the server is configured to verify if the file is an image by examining its content.
In this case, the lab itself provides us with an account to log in, so let’s do that:


Once we have logged in, we find the account profile:

As we can see, we have an option to upload a file, specifically it appears to be for updating the profile avatar. We are going to try to take advantage of this option to upload the following PHP file:

Be careful, if we look closely, in this case, in addition to the PHP code itself, I am defining a string at the beginning of the file. This happens because to determine the content type of a file, the first bytes are used, which is known as “magic numbers”. These first bytes of files determine what type they are or how they will be treated, even if the content is completely different.
As we can see, it contains PHP code, but Linux itself detects it as an image, this happens because of the magic numbers.
Complete list of magic numbers by file type
With this understood, we configure Burp Suite to intercept the requests:


Once we have Burp Suite ready along with the proxy, we select the file and upload it:



Burp Suite will intercept the file upload request:

To better handle the request, we are going to send it to the repeater and at the same time click send to analyze the response:

It seems to have uploaded without problems. Let’s view this response in the browser:




Once here, we no longer need Burp Suite, so we are going to disable the proxy:

With this done, we go to our profile:

Now, if we look at the profile, we can see that the avatar has changed and now shows an error that it doesn’t load the image properly:

This is probably because it is trying to load our PHP file as if it were an image, and of course, it fails to do so. To confirm if it is our PHP file, we right-click to go to the exact path of “the image”:


As we can see, it is indeed our PHP file, and in addition to the string placed to establish the magic numbers, we can see the content of the secret file. In other words, the output of the interpreted PHP code.
Having the content of secret, we simply submit the answer:


And in this way, we solve the lab:


In addition to the solution we have carried out, PortSwigger suggests another quite interesting one worth mentioning:
- We create an
exploit.phpfile that reads the content of Carlos’ssecretfile, for example:<?php echo file_get_contents('/home/carlos/secret'); ?> - We log in and try to upload our PHP file in the avatar section. As we will see, the server blocks any file upload that is not an image.
- We are going to create a polyglot PHP/JPG file. That is, a file that is an image but contains PHP code in its metadata. To do this, it is as simple as using any image and adding custom metadata using
exiftool. Example:exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" <YOUR-INPUT-IMAGE>.jpg -o polyglot.php. This will add the PHP payload to the comment field of the metadata. With this, we will save the image with the.phpextension. - Now, we upload this file, we will see that we have no problem. With this done, we return to our profile.
- If we go to the HTTP History in Burp Suite, we can see a GET request to the supposed avatar image (this request was produced when we accessed our profile and the avatar tried to load). If we take this request and look at its response, we can see the content of Carlos’s
secretfile. - We submit the solution and we will have solved the lab.