Skip to main content
Create your own
Lesson illustration

Race Condition Exploitation with Concurrent Requests

Hello! Welcome back to our module on Authorization Bypass & Logic Flaws.

In our last lesson, we saw how to bypass entire steps in a workflow by manipulating the sequence of requests, violating the developer's assumption of a linear user journey. Today, we're going to exploit an even more subtle developer assumption: that their code will execute one step at a time without interruption.

This lesson focuses on the learning outcome: Use request sequencing tools to send concurrent requests and exploit race condition vulnerabilities. We'll move from manipulating the order of events to manipulating the timing, sending multiple requests so close together that they trip up the server's logic, leading to powerful exploits like redeeming a coupon multiple times or bypassing rate limits.

1. What is a Web Race Condition?

At its core, a web race condition is a vulnerability that occurs when an application's correctness depends on the sequence of operations, but the system doesn't enforce that sequence. This often happens when a process involves multiple steps with a small delay between them, such as checking a value and then using it. This delay is called the race window.

The classic example is a Time-of-Check-to-Time-of-Use (TOCTOU) flaw. The application checks if a condition is met (e.g., "Has this gift card been used?"), and then uses that information to perform an action (e.g., "Apply the discount"). If we can send a second request after the check but before the application marks the card as used, we can exploit the race window.

Let's watch a short video that explains this concept perfectly using a gift card scenario.

Race Conditions - The Bug Hunters Guide

The video "Race Conditions - The Bug Hunters Guide" from Bug Hunter Labs provides an excellent visual introduction to the topic. It clearly defines the race window and TOCTOU flaws.

Watch the video from the beginning until 04:15. Pay close attention to how the two simultaneous requests both pass the 'check' phase before the database state is updated in the 'use' phase.

As the video explains, the vulnerable sequence is:

  1. Request 1 (Time of Check): The server checks the database. "Has gift card XYZ been redeemed?" The database says "No".
  2. Request 2 (Time of Check): Before Request 1 can finish, the server checks the database for our second request. "Has gift card XYZ been redeemed?" The database still says "No".
  3. Request 1 (Time of Use): The server applies the discount and updates the database to mark the card as used.
  4. Request 2 (Time of Use): The server, based on its earlier check, also applies the discount and updates the database again.

The result: we get the discount twice. This "collision" of operations within the race window is the essence of the exploit.

2. The Challenge: Overcoming Network Latency

If it were as simple as sending two requests quickly, these bugs would be easy to find. The main challenge is that requests sent from your computer to a remote server are affected by network latency and network jitter (random variations in latency). These factors make it extremely difficult to ensure your requests arrive at the server's race window at the same time.

Race Window in Concurrent Requests
This diagram illustrates how network latency and jitter can prevent two concurrent requests from aligning perfectly, making it hard to hit the critical race window during the server's internal processing.

To solve this, security researchers have developed sophisticated techniques that are now integrated into modern tools. The goal is to minimize the impact of network jitter.

The most effective of these is the single-packet attack, developed by PortSwigger's Director of Research, James Kettle. This technique leverages features of the HTTP/2 protocol to send the final, completing parts of many requests within a single TCP packet. This effectively eliminates network jitter, making your requests arrive at the server almost simultaneously.

For a deeper technical dive, let's hear about this technique from the person who pioneered its use in web security.

DEF CON 31 - Smashing the State Machine the True Potential of Web Race Conditions - James Kettle

In his DEF CON 31 talk, James Kettle explains the problem of network jitter and how the single-packet attack solves it. His explanation is perfect for your CS background and interest in the 'ins and outs' of the system.

Watch this segment from 06:40 to 11:20. Focus on why last-byte synchronization isn't perfect and how the single-packet attack combines concepts to achieve much higher precision, making 'remote race conditions local'.

The key takeaway is that by using tools that implement the single-packet attack, we can reliably test for race conditions that were previously almost impossible to exploit over the internet.

3. Exploitation in Practice: Burp Suite and a Methodology

Now for the practical part. Your primary tool for this is Burp Suite, specifically the Repeater tool, which has built-in features for sending grouped requests. You don't need to manually craft TCP packets; Burp handles the complexity of the single-packet attack for you.

To find these vulnerabilities systematically, we use a three-step methodology: Predict, Probe, and Prove.

Let's read the official PortSwigger documentation, which outlines both the methodology and the tools.

Race conditions | Web Security Academy

The PortSwigger Web Security Academy provides the definitive guide on this topic. We'll focus on the sections that explain how to use Burp Repeater and the methodology for finding these bugs.

First, read the section "Detecting and exploiting limit overrun race conditions with Burp Repeater". This shows you exactly how to use Burp's new features. Then, read the section on "Methodology" which details the Predict, Probe, Prove approach for finding more complex race conditions.

Let's summarize the workflow:

  1. Predict:

    • Identify a target endpoint. Good candidates are actions that are rate-limited, single-use, or modify a shared state (e.g., applying a coupon, submitting a vote, transferring funds, changing an email address).
    • Craft the request(s) you want to race. For a simple limit overrun, this might be 20 copies of the same request. For more complex attacks, it could be two different requests (e.g., change email and confirm email).
  2. Probe:

    • In Burp Repeater, create a tab for each request and group them.
    • Benchmark: First, send the group in sequence (using separate connections). This shows you the normal, expected behavior. Note the responses, status codes, and any side effects (like emails received).
    • Attack: Now, send the same group in parallel. Burp will automatically use the single-packet attack if the server supports HTTP/2.
    • Look for clues: Compare the results of the parallel attack to your benchmark. An anomaly is any deviation: different status codes, error messages, different response times, extra emails, or misdirected data in those emails.
  3. Prove:

    • Once you find an anomaly, your job is to understand it and turn it into a reliable exploit. This might involve trimming down the number of requests, adjusting timing, or exploring the application to see where else this "structural weakness" can be abused.
Test your understanding!

You are testing an online poll application. Users can vote for one of two options, "Yes" or "No", but are only allowed to vote once. The request to cast a vote is a POST request to /api/vote with a body like {"vote": "yes"}.

Using the Predict, Probe, Prove methodology, describe the concrete steps you would take in Burp Suite to test for a race condition that would allow you to vote multiple times.

Show answer

Here is how you would apply the methodology:

  1. Predict:

    • The target endpoint is /api/vote. This is a security-critical function because it has a "vote once" limit.
    • I will craft a single valid request: POST /api/vote with the body {"vote": "yes"}.
  2. Probe:

    • Open Burp Repeater. Create about 20 tabs, all containing the same vote request. Group these tabs together.
    • Benchmark: Send the tab group using the "Send group in sequence (separate connections)" option. I would expect to see one 200 OK or 202 Accepted response for the first request, and 19 403 Forbidden or 429 Too Many Requests responses with a message like "You have already voted."
    • Attack: Reset the poll if possible. Then, send the same tab group using the "Send group in parallel" option.
    • Analyze Clues: I will look for a deviation from the benchmark. If I see more than one successful (e.g., 200 OK) response, it's a strong clue that the race condition is exploitable. Even if the responses look the same, I would check the vote count on the application's front-end to see if it increased by more than one.
  3. Prove:

    • If the probe was successful, I would try to find the minimum number of parallel requests needed to bypass the limit (e.g., does it work with just two or three requests?).
    • I would document the exact steps, capture the evidence (multiple successful responses, screenshot of the manipulated vote count), and report that sending multiple concurrent requests to the /api/vote endpoint bypasses the single-vote limit.

Conclusion

You've now learned the theory and practical application of one of the most interesting web vulnerability classes. Finding race conditions requires a different mindset—thinking not just about what requests to send, but when and how fast.

Key Takeaways:

  • Race conditions exploit the race window, a brief period where an application's state is inconsistent (a TOCTOU flaw).
  • Modern exploitation relies on overcoming network jitter using techniques like the single-packet attack, which is automated in tools like Burp Suite.
  • Burp Repeater's group send feature is your go-to tool for sending precisely timed concurrent requests.
  • The Predict, Probe, Prove methodology provides a structured approach to move from a potential target to a confirmed vulnerability.

Next Lesson Preview:
In this lesson, we focused heavily on the practical side—how to use tools to send concurrent requests and find the bug. In the next lesson, we will double-click on the theoretical concept we introduced at the start: Time-of-Check-to-Time-of-Use (TOCTOU). We'll formalize our understanding of this flaw, look at different ways it can manifest in code, and explore examples beyond simple limit overruns. This will solidify your conceptual foundation, making you better at predicting where these vulnerabilities might exist.

Can't find a good explanation? Sign up and we'll make it for you

Sign up