🗂️PortSwigger Lab Writeup: Web Shell Upload via Race Condition

🎯 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 exploited using a race condition. 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-race-condition - Category: File Upload
- Difficulty: Expert
🧪 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.


- 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:peterto access file upload function.
- Now, we can see the file upload function where we can upload an avatar of the user.

- Make basic php web shell named
payload.phpwith the given code:<?php echo file_get_contents('/home/carlos/secret'); ?> - Now, Upload this payload.

- You will notice that the request was rejected as only jpg & png files are allowed to upload.

- However, it is mentioned that there is a race condition where our uploaded file is stored on server for some time before validating it.
- We will use this little time of validation to execute our payload.
- Now, first go to account page and open the current uploaded avatar in new tab.
- Currently it will give
404 Not Founderror. - Now, Open the HTTP History in Burpsuite and send both the
POST /my-account/avatarandGET /files/avatars/payload.phprequests to Repeater tab.
- Now, Group both the tabs and set the send type to parallel.
🧑💼Step 3: Access the Secret
- Now, send the group request multiple times and in one of responses you will get the secret of carlos.

- Now, Copy the secret and submit it to complete the lab.

- And Finally, the Lab is solved.
🧠 Conclusion
- This lab exploited a race condition where the server stores uploaded files before validating them, creating a time window where executable code exists on disk. By sending parallel requests, the payload was executed before validation rejected it.
- The impact is critical — attackers can execute arbitrary code by exploiting timing gaps in file validation, defeating synchronous validation approaches.
- Fix: validate files before storing them, use atomic operations (reject then delete), implement strict timeouts, and store uploads outside the webroot with no execute permissions.