Portswigger Labs

Lab 1: RCE via webshell

To solve this lab, upload a basic PHP webshell and read /home/carlos/secret.

When logging into the given account, I saw that I was able to upload Avatars to the website:

The website wants me to upload a PHP web shell, like this:

I tried to upload a cmd.php file, and it worked:

When viewing my new profile, I saw a GET request send to /files/avatars/cmd.php. This webshell allows for RCE:

To solve this lab, just replace id with cat+/home/carlos/secret.

Afterwards, I scripted the entire process.

Lab 2: Content-Type Restriction Bypass

Just reading the lab title told me what to do. In the above script, replace the file parameter with this:

Previously, it was set to application/x-php. When set to that, the website blocks it:

By changing the Content-Type header (which is the 3rd parameter in file), I can bypass this.

Lab 3: Path Traversal + Web shell

This lab does not check the Content-Type header, but execution of the webshell is not as straightforward.

For this, the lab title tells us that one has to combine path traversal with this. This means that the directory of which avatars are uploaded blocks the execution of PHP code.

As such, I can rename the file to ../evil.php so that it appears in the previous directory.

For this, I renamed the file to ..%2fevil.php, and accessed it at /files/evil.php instead of /files/avatars/evil.php.

The above prints the flag out.

Lab 4: Extension Blacklist Bypass

This lab has a blacklist on the allowed file extensions.

There is a file that is blocking my PHP file. For this case, I tried the .htaccess upload trick.

Firstly, I can try to upload this .htaccess file as text/plain:

Then, I can proceed with the regular script:

Lab 5: Obfuscated Extension

When trying to upload a file, this is the error I get:

Changing it to evil.jpg.php doesn't work. However, uploading evil.php%00.jpg works, and it is uploaded as evil.php.

The rest of the exploit is as per normal:

Lab 6: Polyglot Webshell

This lab really checks whether the file uploaded is an image. As such, I just created a webshell like so:

Then, I uploaded this sample.jpg file with a payload embedded within it, but it didn't execute.

When I changed it to sample.php instead, it worked.

This means that the website was indeed checking whether a valid image was uploaded, but it still allowed the execution of PHP code.

Lab 7: Race Condition

The lab has a race condition, and I suppose it is because it deletes the file quickly.

I found that using the NULL byte trick works:

Here's the code from the website:

The problem with the code above is that it moves the file before checking it.

This means that for a brief period, the file is available on the website, and it can be used for code execution BEFORE it is removed via unlink.

This means I don't have to even use a NULL byte. Even if the website tells me the file upload failed, the file is still present on the website for a brief moment.

Using 2 Python scripts to exploit this race condition is the easiest.

There are 2 scripts needed, one to continuously upload a cmd.php file, and one that keeps trying to read the secret:

Running these two in separate terminals will eventually print out the secret.

Last updated