Introduction
Race conditions are a common and dangerous class of security vulnerabilities that arise when multiple processes or threads access shared resources in an unsynchronized manner. In the context of web applications, these vulnerabilities can lead to serious issues such as privilege escalation, financial fraud, or unauthorized access.
In this blog, we’ll dive into PortSwigger’s Lab 4: Single-endpoint race conditions, which is part of their Web Security Academy’s race condition module. This particular lab demonstrates how even a single vulnerable endpoint — when accessed concurrently — can lead to unintended and insecure behavior if proper locking or validation mechanisms are not in place.
Through this walkthrough, we’ll explore how to identify, exploit, and understand the underlying risk of such vulnerabilities, and also discuss potential mitigations that developers can adopt to secure their applications.
Challenges
This lab’s email change feature contains a race condition that enables you to associate an arbitrary email address with your account.
Someone with the address carlos@ginandjuice.shop
has a pending invite to be an administrator for the site, but they have not yet created an account. Therefore, any user who successfully claims this address will automatically inherit admin privileges.
To solve the lab:
- Identify a race condition that lets you claim an arbitrary email address.
- Change your email address to
carlos@ginandjuice.shop
. - Access the admin panel.
- Delete the user
carlos
You can log in to your own account with the following credentials: wiener:peter
.
You also have access to an email client, where you can view all emails sent to @exploit-<YOUR-EXPLOIT-SERVER-ID>.exploit-server.net
addresses.
Walkthrough
Step 1: To begin, we log into the application using the default credentials provided by the lab. This gives us access to the user dashboard, which is essential for interacting with the vulnerable functionality in the next steps.
Step 2: Observed that wiener’s account is linked to an email ID, which we plan to replace with ours to gain admin access.
Step 3: We have access to a mailbox that only accepts emails from the same domain, and we’ll attempt to exploit this restriction to our advantage.
Step 4: To test the email update functionality, we submitted a new email address within the same domain to check if it gets accepted.
Step 5: A popup appeared prompting us to confirm the email address via the verification link sent to the mailbox.
Step 6: Received the confirmation email in the mailbox showing the sender, recipient, and confirmation link—clicked on the link to proceed.
Step 7: Upon clicking the confirmation link, a success message appeared confirming the email update.
Step 8: Identified the request responsible for updating the email ID and triggering the confirmation email to the mailbox.
Step 9: Sent the same request to the repeater five times, modifying the email in each request incrementally (e.g., asad1, asad2, asad3, etc.).
Step 10: Created a group tab as done in the previous lab and selected “Send group in parallel (single-packet attack)” to trigger all requests simultaneously.
Step 11: Checked the mailbox and noticed that the “To” address and the confirmation email ID didn’t match across all requests, clearly indicating a race condition.
Step 12: Now, we modify the email ID in one of the requests to Carlos’s email and resend the group of requests.
Step 13: Received a confirmation email for Carlos’s email ID, even though the request was originally sent for asad3 — the race condition caused the requests to mix, resulting in Carlos’s email being updated.
Step 14: After confirming the email, a success message appeared, indicating the email was updated successfully.
Step 15: Noticed that the admin panel wasn’t accessible with our previous email ID—refreshed the page to check for any changes.
Step 16: After refreshing the page, Carlos’s email ID was updated to ours, and the admin panel became accessible.
Step 17: As per the lab instructions, the final step is to delete the Carlos user to successfully complete the lab.
Step 18: Successfully completed the lab by exploiting the race condition and fulfilling the objective.