Skip to main content

🗂️PortSwigger Lab Writeup: Remote Code Execution via Polyglot Web Shell Upload

PortSwigger lab banner showing polyglot file upload technique for RCE


🎯 Objective

The objective of this lab is to exploit a file upload vulnerability where the app has a vulnerable image upload function which can be bypassed using polyglot file. The goal is to upload a basic web shell and exfiltrate the contents of file /home/carlos/secret

  • Lab URL: https://portswigger.net/web-security/file-upload/lab-file-upload-web-shell-upload-via-polyglot-web-shell-upload
  • Category: File Upload
  • Difficulty: Practitioner

🧪 Exploitation Steps

🕵️Step 1: Observe the Website

  • Firstly open the lab URL in your browser, and observe what it is about and how it works. Blogging website homepage displaying blog posts and navigation menu
    Login page interface with username and password fields
  • At first glance, the website seems to be a blogging website with a login page. In the lab description, it is mentioned that we need to exfiltrate the secret of carlos.

📝Step 2: Upload the payload

  • First login with the given credentials - wiener:peter to access file upload function. Login page with wiener credentials
  • Now, we can see the file upload function where we can upload an avatar of the user. User profile page with file upload form for avatar image
  • Make basic php web shell named payload.php with the given code:
    <?php echo file_get_contents('/home/carlos/secret'); ?>
  • Now, Upload this payload. File upload dialog showing payload.php file selected for upload
  • You will notice that the request was rejected as only jpg & png files are allowed to upload. Upload rejection message showing only image file extensions are permitted
  • Therefore, we will try to bypass this using a polyglot file.
  • We will use the tool exiftool to make a polyglot file. Use the given command to create.
    exiftool -Comment="<?php echo 'START' . file_get_contents('/home/carlos/secret') . 'END'; ?>" 65.jpg -o polygot.php
  • This creates a file that is simultaneously a valid JPEG (with magic bytes intact) and PHP code in the EXIF metadata, bypassing content-type and magic byte checks.
  • Now, upload this polygot.php by using Null Byte and you will see that our polygot file was uploaded successfully to the server.

🧑‍💼Step 3: Access the Secret

  • Open the uploaded web shell at /files/avatars/polygot.php
  • Now, Open the HTTP History in Burpsuite and see the GET /files/avatars/polygot.php response.
  • Search for the string START in the response and copy the secret until you found the string END Burp HTTP history showing polyglot.php response with secret data between START and END markers
  • Now, Copy the secret and submit it to complete the lab. Lab solved confirmation message displaying after submitting correct secret
  • And Finally, the Lab is solved.

🧠 Conclusion

  • This lab demonstrated polyglot file technique where a valid JPEG image containing PHP code in EXIF metadata bypasses both content-type and magic byte validation checks.
  • The impact is critical — polyglot files allow attackers to upload executable code disguised as valid binary files, completely circumventing format-based defenses.
  • Fix: validate file contents extensively (not just headers), disable script execution in upload directories, use cryptographic signatures or external sandboxing, and store uploads outside the web root.