Smashing the State Machine: The True Potential of Web Race Conditions
This talk demonstrates a novel 'single-packet attack' technique that leverages HTTP/2 and TCP stack behavior to reliably trigger race conditions in web applications, bypassing network jitter. The researcher applies this methodology to identify and exploit race conditions in complex multi-step workflows, such as email verification and account management systems. The presentation highlights how modern web frameworks often fail to maintain state consistency across asynchronous operations, leading to critical vulnerabilities like account hijacking. A new feature for the Turbo Intruder tool is released to facilitate this attack.
Smashing the State Machine: Why Your Race Condition Payloads Are Failing
TLDR: Most web race condition exploits fail because network jitter prevents multiple requests from hitting the server simultaneously. By leveraging HTTP/2 and TCP stack behavior, researchers can now bundle multiple requests into a single packet to bypass this jitter and trigger race conditions with surgical precision. This technique turns previously "unexploitable" race conditions into reliable, high-impact vulnerabilities like account hijacking and privilege escalation.
Race conditions in web applications have long been considered the "flaky" cousin of vulnerability classes. Pentesters often spend hours trying to time their requests perfectly, only to be thwarted by the unpredictable nature of network jitter. We have all been there: you fire off a burst of requests, hoping to hit a narrow window in the application logic, but the server processes them in a slightly different order every time. It is frustrating, inefficient, and often leads to the conclusion that a target is secure when it is actually just protected by the laws of networking physics.
James Kettle’s research at Black Hat 2023 fundamentally changes this dynamic. By moving away from the traditional "last-byte sync" approach and utilizing HTTP/2 features to force simultaneous request execution, he has effectively turned remote race conditions into local-feeling exploits. This is not just a theoretical improvement; it is a shift in how we should approach state-based vulnerabilities in modern web stacks.
The Single-Packet Attack
The core problem with traditional race condition testing is that each request is an independent entity subject to the vagaries of the internet. Even if you send them at the same time, network congestion and server-side processing variations ensure they arrive at the application layer at different times.
The "single-packet attack" solves this by exploiting how web servers handle HTTP/2 streams. Because HTTP/2 allows multiplexing multiple requests over a single TCP connection, you can craft a payload that holds back the final byte of each request. By withholding that last byte, you force the server to buffer the requests. Once you release that final byte for all requests simultaneously, the server processes them in a tight, synchronized burst.
This approach effectively eliminates network jitter as a variable. You are no longer racing against the network; you are racing against the server’s internal processing speed. This is a massive leap forward for anyone doing web security testing.
Technical Implementation
To implement this, you need a tool that can manipulate the TCP stack and HTTP/2 framing. The updated Turbo Intruder extension for Burp Suite now includes this functionality. The logic is straightforward: you disable TCP_NODELAY to allow the OS to buffer your packets, then you queue your requests with the final byte withheld.
# Conceptual snippet for Turbo Intruder
engine = RequestEngine(endpoint=target, concurrentConnections=1)
# Queue requests with the final byte withheld
for i in range(20):
engine.queue(target.req, gate='race1')
# Release the gate to trigger the synchronized burst
engine.openGate('race1')
The beauty of this is that it works on almost any modern web server that supports HTTP/2. You do not need to write custom TCP or TLS stacks. You just need to understand the state machine of the application you are testing. If you can identify a multi-step process—like an email change or a password reset—where the application transitions through an insecure intermediate state, you have a target.
Real-World Applicability
During his demo, Kettle showed how this could be used to hijack email verification processes on GitLab. By sending a burst of requests that changed the email address while the server was validating the token, he could force the server to associate a token with an attacker-controlled email address. This is a classic Broken Access Control scenario, but one that is nearly impossible to trigger without this level of synchronization.
For a pentester, this means you should stop looking for simple "limit-overrun" bugs and start looking for state-machine flaws. Look for endpoints that perform sensitive operations in multiple steps. If an application reads a record from a database, modifies it, and then writes it back, there is a potential race window. If that window is protected by a multi-threaded batch job or an asynchronous background process, your chances of success are high.
Defensive Considerations
Defending against these attacks is difficult because the vulnerability often lies in the architecture rather than the code. If your application relies on insecure intermediate states, no amount of input validation will save you.
Blue teams should focus on using atomic operations and database-level constraints to ensure that state transitions are truly atomic. If you are using a session handler, ensure it is not susceptible to batch-processing flaws. The goal is to make the state transition "all or nothing." If the application can be forced into a state where it has partially processed a request but not yet finalized the security context, you have already lost.
This research proves that our assumptions about "unexploitable" race conditions were wrong. The next time you are staring at a multi-step authentication flow, do not just look for logical flaws. Look for the race. With the right tooling and a bit of patience, you can force the application to reveal its state-machine secrets. Stop guessing with your payloads and start controlling the timing.
Vulnerability Classes
Tools Used
Target Technologies
All Tags
Up Next From This Conference

Chained to Hit: Discovering New Vectors to Gain Remote and Root Access in SAP Enterprise Software

Zero-Touch-Pwn: Abusing Zoom's Zero Touch Provisioning for Remote Attacks on Desk Phones

ODDFuzz: Hunting Java Deserialization Gadget Chains via Structure-Aware Directed Greybox Fuzzing
Similar Talks

Kill List: Hacking an Assassination Site on the Dark Web

Firewalls Under Fire: China's Ongoing Campaign to Compromise Network Protection Devices

