Hello! Welcome back to our module on Authorization Bypass & Logic Flaws.
In our last lesson, we focused on the practical mechanics of exploiting race conditions, using Burp Suite to send concurrent requests and overrun application limits. You learned the Predict, Probe, Prove methodology and saw how techniques like the single-packet attack make these vulnerabilities exploitable.
Today, we're going to build on that practical knowledge by exploring the fundamental conceptual flaw that makes most of these race conditions possible. This lesson focuses on the learning outcome: Explain time-of-check-to-time-of-use (TOCTOU) race condition flaws in the context of web applications.
By understanding the why behind the exploit, you'll become much more effective at the "Predict" phase of your testing, enabling you to spot potential race conditions in complex application logic that others might miss.
1. From Concurrency Bugs to TOCTOU Vulnerabilities
Given your background in Computer Science, you're likely familiar with concurrency and the bugs that arise when multiple threads access shared resources without proper synchronization. A race condition is exactly that: a bug where the system's behavior depends on the non-deterministic sequence or timing of threads or processes.
In the context of security, this bug becomes a vulnerability when it undermines a security control. This specific type of vulnerability is often called a Time-of-Check-to-Time-of-Use (TOCTOU) flaw.
A TOCTOU flaw occurs when an application:
- Checks for a certain condition or the state of a resource.
- Uses the result of that check to perform a sensitive action.
The vulnerability exists in the tiny window of time—the race window—between the check and the use. If an attacker can influence the resource or state within that window, the "use" becomes invalid.
Let's watch a video that perfectly explains this transition from a general concurrency bug to a specific TOCTOU security vulnerability.
Hacking banks with race conditions
The video "Hacking banks with race conditions" by Vickie Li provides a concise explanation of concurrency and then defines TOCTOU vulnerabilities using a clear example.
Watch from 01:59 to 04:53. Pay close attention to how she defines a TOCTOU vulnerability and then applies it to a bank transfer scenario, which is a classic example of this flaw.
As the video demonstrated, the sequence for the bank transfer vulnerability is:
- Thread 1 (Check): Does Account A have $500? Yes.
- Thread 2 (Check): Does Account A have $500? Yes. (This happens before Thread 1 deducts the money).
- Thread 1 (Use): Deduct $500 from A, add $500 to B.
- Thread 2 (Use): Deduct $500 from A, add $500 to B.
The check was valid at the time it was made, but the state of the shared resource (Account A's balance) changed before the second 'use' operation completed.
2. Visualizing the Race Window
The limit overrun attacks we discussed in the previous lesson, like redeeming a gift card multiple times, are a classic subtype of TOCTOU flaws.
Let's look at a diagram that visualizes this concept in the context of a web application.

To see this in motion, we can revisit the Bug Hunter Labs video from our last lesson, this time focusing specifically on its explanation of the race window.
Race Conditions - The Bug Hunters Guide
The video "Race Conditions - The Bug Hunters Guide" provides an excellent animation of the TOCTOU concept.
Watch the clip from 02:31 to 04:15. Notice how the narrator explicitly labels the 'Time of Check' (querying the database) and the 'Time of Use' (applying the discount and updating the database).
3. TOCTOU in Complex Web Applications: Hidden Sub-states
While examples like gift cards and bank transfers are clear, TOCTOU flaws in modern web applications are often more subtle. They don't always map to a simple if (check()) { use(); } block in the code.
A single HTTP request can trigger a complex series of operations on the server, causing the application to move through multiple temporary, hidden states before sending a response. James Kettle of PortSwigger calls these "sub-states". The race window is the time the application spends in one of these exploitable sub-states.
The key insight is: with race conditions, everything is multi-step. A seemingly atomic request is not atomic at all. This is where TOCTOU flaws hide.
Let's dig into the whitepaper that introduced this concept. This material is advanced, but it perfectly aligns with your goal of understanding the "ins and outs" of the system.
The whitepaper "Smashing the state machine" by James Kettle is a seminal work on modern web race conditions. We'll focus on the section that introduces the concept of sub-states, which is the key to understanding complex TOCTOU flaws.
Read the section titled "The true potential of web race conditions". Focus on the idea that requests are not atomic and can transition an application through fleeting 'sub-states'. The state machine diagrams are particularly useful for visualizing this.
This idea of sub-states expands the TOCTOU model. The "check" might be the server putting the application into a privileged temporary state (like is_admin = true), and the "use" is the subsequent part of the code that revokes that privilege (is_admin = false). The race is to send another request that gets processed while the application is in that privileged sub-state.
4. Categorizing TOCTOU Flaws
Understanding the sub-state model allows us to categorize different manifestations of TOCTOU flaws in web applications.
-
Limit Overrun (The Classic TOCTOU):
- Check: Has this coupon been used?
- Use: Apply the coupon and mark it as used.
- Race: A second request checks before the first one has marked the coupon as used.
-
Multi-Endpoint Collisions: The TOCTOU flaw is spread across two or more different endpoints.
- Endpoint A (Check): A request to
/validate-paymentchecks that the cart total matches the payment amount. This check passes. - Endpoint B (Interference): A concurrent request to
/add-to-cartadds a new item. - Endpoint A (Use): The
/validate-paymentlogic continues and confirms the order, but the cart state has now changed since the initial check.
- Endpoint A (Check): A request to
-
Single-Endpoint Collisions: A single, complex endpoint has an internal race condition. This is often seen in functionality that uses background threads, like sending emails.
- Request 1 (Check): A request to
/change-emailwithemail=attacker@site.comstarts processing. The application checks the user's session and setsuser.unconfirmed_email = 'attacker@site.com'. - Request 2 (Check): A parallel request with
email=victim@site.comruns. It also checks the session and setsuser.unconfirmed_email = 'victim@site.com', overwriting the value from Request 1. - Request 1 (Use): The first process, still running, now sends the confirmation email. But when it looks up the email address to send to, it reads the current value from the database:
victim@site.com. However, the confirmation token it includes was generated forattacker@site.com. The result: the victim receives a confirmation link for the attacker's email address.
- Request 1 (Check): A request to
Test your understanding!
An application allows administrators to add new users. The process is handled by a single endpoint, POST /api/users, which performs the following steps in order:
- Creates a new user record in the database with a username and a temporary, insecure password.
- Creates an entry in a separate
permissionstable, linking the new user's ID to a "standard-user" role ID. - Sends an email to the new user with a link to set their final password.
Describe the TOCTOU flaw here. What is the "check" (or initial state), what is the "use" (or final state), and how could you exploit the race window?
Show answer
This is an example of a partial construction race condition, which is a type of TOCTOU flaw.
- The Check (Implicit): The implicit check is the assumption by the system's designers that a user account will always have a role assigned to it upon creation. Any security control that queries this user would expect to find a role.
- The Use: The final state where the user is fully created and assigned the "standard-user" role.
- The Race Window & Exploit: The race window exists between step 1 (user record created) and step 2 (permission assigned). In this sub-state, a user exists but has no role assigned.
- Exploit: An attacker could send a second, concurrent request to an API endpoint like
/api/meor/api/perform-actionimmediately after initiating the user creation. If this second request is processed within the race window, the application might query for the user's role, find it to benullor unassigned, and fail open—granting default admin privileges or bypassing a security check that was expecting a "standard-user" role.
- Exploit: An attacker could send a second, concurrent request to an API endpoint like
Conclusion
You have now moved beyond simply executing race condition attacks to understanding the theoretical model that underpins them. This is a critical step toward expert-level proficiency.
Key Takeaways:
- TOCTOU is the fundamental security flaw where a time gap between a security check and a resource use allows for malicious interference.
- In web applications, the race window often manifests as a temporary, hidden sub-state that an application passes through while processing a single request.
- Recognizing that "everything is multi-step" allows you to predict where TOCTOU flaws might exist in complex workflows, even across multiple endpoints or within a single, complex one.
- This conceptual understanding is your most powerful tool for the "Predict" phase of hunting for logic flaws.
Next Lesson Preview:
In the next and final lesson of this module, we will explore how to chain an authorization bypass with another vulnerability to escalate impact. Understanding fundamental flaws like TOCTOU and IDOR is the first step. The ultimate goal is to combine these "structural weaknesses" to achieve a far greater impact than any single vulnerability could on its own.