Can a single millisecond let attackers turn a $100 purchase into a $1 bargain? That split-second question frames why timing bugs matter to any application that handles concurrent actions.
Race condition vulnerabilities occur when parallel processes touch shared state without proper locks, producing inconsistent outcomes. In payment and account flows, those tiny windows can let an attacker stack discounts or redeem a gift card twice before the database updates.
Research from PortSwigger shows precise vectors like HTTP/1.1 last-byte sync and HTTP/2 single-packet methods. Tools such as Burp Suite and Turbo Intruder make parallel requests reliable, narrowing jitter and raising success rates.
Real CVEs—GitLab email forgery, Linux Dirty COW, and nopCommerce duplicate redemptions—prove these timing issues cause data loss, privilege escalation, and business logic bypass. This guide blends research-backed techniques with practical steps so you can find, reproduce, and help fix these bugs safely.
Key Takeaways
- Understand what a race condition is and why timing matters in payment flows.
- Learn dominant web vectors: HTTP/1.1 last-byte and HTTP/2 single-packet techniques.
- Use tools like Burp Suite and Turbo Intruder to reproduce high-fidelity parallel requests.
- Study real CVEs to see the range of impacts on data and access control.
- Focus on detection, controlled testing, and actionable fixes that fit developer workflows.
Understanding race conditions: definition, root causes, and why timing matters
A race condition happens when parallel execution paths access the same resource without proper synchronization. In that moment, final results depend on execution order and tiny timing differences. Keep this idea front and center: small time windows can change outcomes from correct to unsafe.

Shared resources, threads, and processes: the state goes inconsistent
A race occurs when multiple threads or processes touch shared resources without locks. One actor may check a value while another updates it, so the final state depends on which sequence wins.
From code to application behavior: TOCTOU and hidden sub-states
The classic TOCTOU (time-of-check to time-of-use) type splits a validation and its action, creating a fragile window. Modern web stacks add hidden sub‑states inside a single request — for example, a session granted briefly before a second-factor check. Those temporary conditions let overlapping operations produce unexpected data and state.
- Why timing matters: milliseconds and network jitter reorder actions.
- What to watch: non-atomic sequences, interleaved code paths, and inconsistent server state.
How do hackers exploit race condition vulnerabilities
Attackers target the tiny interval between validation and commit to force overlapping updates. This short intro explains the core concept and what follows: practical tactics for provoking and observing those brief windows.

The race window: aligning checks, use, and precise timing
The race window is the brief moment when a check passes but before the system commits the change. Attackers send multiple requests at nearly the same instant to hit that slot and force collisions.
Multiple requests increase odds by covering more microsecond-scale windows. Tools and synchronization tricks reduce jitter so those hits land together.
Probabilistic vs deterministic exploits in real-world apps
Some attacks are probabilistic and need many tries to win the small window. Others become deterministic when single-packet delivery or strong synchronization gates make ordering predictable.
- Probabilistic: many attempts, higher noise, lower predictability.
- Deterministic: synchronized delivery, consistent ordering, fewer tries.
- Trade-offs: more requests raise detection risk; fewer, well-timed requests may succeed silently.
| Aspect | Probabilistic | Deterministic |
|---|---|---|
| Attempts required | Many | Few |
| Timing control | Basic parallel sends | Single-packet or last-byte sync |
| Success predictability | Variable | High |
| Detection risk | Higher with volume | Lower with precision |
Inspect server threads and processes to see why a condition surfaces only sometimes. Instrumentation and logging during tests reveal when a slot flips, helping you reproduce issues reliably. For further reading on practical cases, see this write-up on multiple-vote scenarios: multiple-vote race example.
Attack taxonomy: TOCTOU, limit overruns, and state machine abuses
A clear taxonomy separates basic TOCTOU issues from complex state-machine abuses that surface under load. Understanding categories helps testers cover simple overruns and subtle multi-step flaws in the same sweep.
TOCTOU stands for time-of-check to time-of-use. It describes checks that run before an action, creating a short window attackers can target.

Limit overruns and rate counters
Limit overrun attacks reuse coupons, gift cards, or rate-limited actions by racing validation and update steps. Two near-simultaneous requests may both see an “unused” flag before the system marks it used.
- Rate-limit bypass: counters increment after acceptance, not atomically with the check.
- Business logic impact: duplicate redemptions and fraudulent orders.
Hidden sequences and state-machine abuses
Many flaws live in multi-step sequences inside a single request. Sub-states—payment validated, items added, confirmation pending—can be manipulated by aligning order across parallel actions.
These problems often involve shared resources touched by multiple code paths. Mapping real execution, documenting observed sequences, and enforcing atomic transitions are essential to fix the flaw and prevent condition exploits and race condition exploits.
HTTP/1.1 last-byte synchronization attacks
Holding the final byte of an HTTP/1.1 request open can force servers to begin a second request while the first remains active. This creates a controlled overlap in server processing that reveals tiny timing windows in update logic.

Last-byte synchronization works by keeping one TCP stream active so the server allocates threads or processes for a second incoming request. Both requests may reach the validation step before any state update runs.
- Mechanic: withhold the final byte to keep a request open and send a follow-up request that the server begins handling in parallel.
- Tools: Burp Suite Repeater groups parallel sends for HTTP/1.1; Turbo Intruder adds gates and retries for stability.
- When to test: endpoints that validate then update state—coupons, counters, balances.
- Practical tips: compare server logs and responses, add small delays to stabilize ordering, and use sandboxed accounts to test safely.
| Aspect | Last-byte sync | Impact |
|---|---|---|
| Primary action | Hold final byte, send parallel request | Creates overlapping operations |
| Tools | Burp Repeater, Turbo Intruder | Controlled timing and retries |
| Typical targets | Validation → update endpoints | Duplicate updates, inconsistent state |
| Network factor | Reduces jitter impact | Improves reproducibility multiple times |
HTTP/2 single-packet race condition attacks
HTTP/2 single-packet delivery groups final fragments so many requests complete at once, removing network jitter from the equation. This method boosts reproducibility by making internal ordering inside the server the primary variable.
The technique queues small portions of each request and releases the final frames together. When twenty to thirty requests finish within a single TCP packet, external arrival variance drops to near zero.

Neutralizing jitter by bundling fragments
Queue partial frames for each stream, then flush the last fragment simultaneously. The server sees a tight burst and ordering depends on internal threads and processes rather than the network.
When multiplexing widens timing gaps
HTTP/2 multiplexing can amplify subtle timing differences inside an application. Multiple logical streams handled on one connection often create exploitable windows across operations that touch shared state.
- Practical tip: in Turbo Intruder set engine=Engine.BURP2, concurrentConnections=1, and use gates to sync final-fragment release.
- Start with many requests to map the vulnerable window, then reduce to the minimum that yields a stable proof-of-concept.
- Log precise timings and correlate backend traces to prove this is an internal ordering issue, not a network artifact.
This approach shines when last-byte sync is unreliable or the window is exceptionally tight. Common scenarios include applying a discount code or confirming payment while another request mutates cart state. Remember: a single request can trigger multiple backend operations, so the visible impact may appear in later state changes rather than the immediate response.
For deeper background on preventing these flaws in application flows, see what is a race condition.
Tools of the trade: Burp Suite Repeater and Turbo Intruder for precise timing
Controlled tooling turns fleeting overlaps into clear proofs that developers can fix.
Use native Repeater modes for quick checks, and move to scripting when you need high-fidelity orchestration.

Burp Suite Repeater (2023.9) can group tabs and fire parallel sends, auto-selecting last-byte sync for HTTP/1.1 or single-packet mode for HTTP/2. This removes much network jitter and simplifies early testing.
When tests need more control, use turbo intruder. Set engine=Engine.BURP2 with concurrentConnections=1 and use gate tags like engine.queue(…, gate=’X’) plus engine.openGate(‘X’) to release many requests at once. That pattern yields synchronized bursts and supports retries, staggered timing, and large volumes.
Repeater parallel sends: last-byte sync vs single-packet modes
Start with grouped tabs to compare modes. Last-byte sync holds a final byte to create overlap. Single-packet groups final frames so server ordering becomes the main variable.
Turbo Intruder gates, BURP2 engine, and high-fidelity concurrency
Gates let you hold thousands of queued requests and open them together. This tightens control over multiple threads and concurrency, making intermittent findings repeatable and debuggable.
Choosing between native features and scripting for complex races
Use Repeater for quick scans and simple multiple-requests checks. Move to scripts when you need orchestration across endpoints or when minimal, stable proofs require retries and fine delays.
| Tool | Best for | Key feature | When to use |
|---|---|---|---|
| Burp Suite Repeater | Quick validation | Last-byte sync / single-packet | Early triage and smoke tests |
| Turbo Intruder | High-volume orchestration | Engine.BURP2, gates, scripting | Complex multi-endpoint or high-fidelity proofs |
| Combined | Reproducible proofs | Group sends + scripted release | Turn intermittent findings into clear reports |
Methodology to discover novel race conditions in modern web apps
Map, probe, and prove: a repeatable approach that turns timing oddities into actionable reports. This method helps you find collisions, measure their impact, and produce a minimal proof engineers can fix.

Predict collisions: map endpoints that touch the same record or transactions. Prioritize security‑critical routes that update shared data. These hotspots offer the best chance of observable clashes.
Probe for clues: benchmark sequential behavior to set a jitter baseline. Then send parallel requests with single‑packet or last‑byte sync and note deviations. Treat altered responses, changed emails, or downstream differences as evidence of a timing condition.
Prove and refine: remove extra requests, isolate the smallest repeatable set, and stabilize timing. Document exact timing and observed information so engineers can trace root causes. Consider users and authorization boundaries to see if collisions cross accounts.
- Use Burp’s “Trigger race conditions” action to automate grouped sends.
- Neutralize network variance with single‑packet techniques when needed.
- Capture before‑and‑after states to show true state‑machine failures.
| Phase | Goal | Technique | Output |
|---|---|---|---|
| Predict | Find shared‑record endpoints | Endpoint mapping, priority list | Target list |
| Probe | Detect timing anomalies | Baselines, parallel sends, single‑packet | Deviation logs |
| Prove | Minimal reproducible case | Request reduction, stable timing | Small PoC + timing notes |
| Scale | Assess system impact | Related endpoints testing | Impact report |
For a practical reference and further reading, see the ultimate guide to race condition vulnerabilities.
Single-endpoint and multi-endpoint races: where collisions actually occur
Single endpoints often hide surprising cross-talk, while multi-endpoint flows expose timing links between routes. These collisions can change who owns a token, which update wins, or how the application records a transaction.
Single-endpoint value collisions
A single endpoint can overwrite session fields when two parallel inputs reach it. For example, two submissions from the same session with different usernames can leave a valid reset token tied to the wrong account.
Test tip: fire multiple requests to the same route and compare session-backed values before and after. Look for mismatches in cookies, tokens, or IDs that indicate state was lost or swapped.
Multi-endpoint flows and aligned windows
Multi-endpoint races require aligning timing across routes, such as adding items to a cart while a separate payment call completes. Use single-packet bursts to start events together, then tweak timings to match backend processing order.
- Warm connections: pre-open connections to remove startup jitter.
- Create delays: trip limits or resource gates to nudge server-side timing without adding network variance.
- One request, many effects: test endpoints that trigger multiple backend operations — they often reveal hidden state transitions.
Minimize noise: control headers, isolate sessions, send minimal payloads, and capture clear before/after records. Confirm that observed differences reflect real state changes and not transient errors.
Real-world exploits and CVEs that illustrate impact
Concrete incidents show timing flaws cause more than odd errors — they enable account takeover, privilege escalation, and direct financial loss. These examples make clear where to focus remediation and detection.
Consider CVE-2022-4037 in GitLab CE/EE: a small race let verified email forgery occur, which then enabled third-party OAuth account takeover. That shows how a sequence error in identity flows can cascade into full user account compromise.
CVE-2016-5195, known as Dirty COW, proved kernel-level code paths and core processes are not immune. Local copy-on-write timing allowed privilege escalation and persistent system access.
In web commerce, nopCommerce before 4.80.0 lacked proper locking during order placement. Attackers redeemed gift cards multiple times and drained balances, a clear business-impact example repeated in public bounty reports.
- Signals for defenders: timestamps, logs, and response diffs that show identical checks passing in the same order.
- Repeated success multiple times implies systemic issues, not one-off bugs.
- Cross-check CVE entries and vendor advisories for mitigation steps and context.
Security impacts: data corruption, business logic abuse, DoS, and access control bypass
Timing flaws in concurrent flows cause real damage: corrupted records, broken rules, service outages, and lost trust. Defenders must see these as system risks, not rare bugs.
Data corruption appears when two operations write conflicting values and leave the application in an inconsistent state. Restores and audits often miss the subtle mismatches that slip into backups.
Business logic abuse shows up as stacked discounts, duplicate redemptions, or double-spent balances. Small timing gaps translate directly into financial and reputational harm.
Denial-of-service can follow unstable state transitions. Exceptions, retries, or deadlocks under load exhaust resources and knock services offline.
Access control bypass occurs when identity checks and enforcement diverge in time. One mis-ordered write can let an attacker pass a multi-step gate before protections apply.
- Root cause: threads touching shared resources without atomic operations.
- Ripple effects: a single bad write can cascade into downstream systems.
- Fix priority: harden critical operations with serialization and atomic updates.
“Sporadic anomalies in logs are often signs of a timing issue, not just flaky infrastructure.”
Pair detection with targeted chaos and concurrency tests. That pairing helps teams find faults early and protects revenue, compliance, and customer trust.
Defensive strategies: making state changes atomic and race-safe
Make critical updates atomic and remove brief windows where parallel requests can change shared state. These practical steps tie checks and writes together so the application keeps a clear order and strong integrity.
Start with transactions that guarantee either full commit or full rollback. Use ACID transactions to bind validation and mutation into one unit so one failure does not leave partial changes.
Locks and serialization at the row level
Apply row-level locks such as SELECT … FOR UPDATE to serialize access to critical records. This prevents interleaved writes when concurrent operations touch the same row.
Idempotency, optimistic locking, and single-step server logic
Introduce idempotency keys and optimistic locking (version numbers) to detect conflicts before applying updates. Consolidate validation and mutation into a single server-side function to remove the split-second window attackers target.
Distributed systems: locks, limits, and session warnings
Design robust distributed locks and pair them with rate limiting to protect shared resources. Avoid relying on session fields for business limits; they can desynchronize under parallel calls and lead to limit overruns or data loss.
Continuous testing and incident playbooks
Bake concurrency tests into CI—stress runs, targeted fuzzing, and language-specific race detectors (for example, Go race detector). Maintain clear invariants in code and a playbook for repair and temporary serialization if a suspect timing issue appears.
- Key wins: fewer production anomalies, stronger data integrity, and reduced race condition exploits in critical paths.
- For background on terminology and prevention, see what is a race condition vulnerability.
Hands-on learning paths and research to stay current
Active labs and recent papers turn abstract timing theory into repeatable tests. Practice builds instinct: run examples, capture traces, and refine scripts so your findings translate into fixes.
Active practice in curated labs reveals subtle timing patterns that reading rarely exposes. Start with PortSwigger’s public labs; they simulate limit overrun and hidden multi-step flows that mirror real app logic.
Practice labs: limit overrun and hidden sub-state scenarios
Run the PortSwigger exercises to see failures in a controlled setting. These labs replicate both simple overuse cases and nuanced sub-state issues from Black Hat USA 2023 research.
Capture server logs and compare states before and after tests. Collect a short catalogue of inputs, outputs, and timings as a reusable playbook for your team and other users.
Latest research on single-packet techniques and state machine attacks
Read James Kettle’s “Smashing the State Machine” for single-packet methods and sample scripts that use engine=Engine.BURP2 and gates. That work explains why bundling final frames removes network jitter and shifts ordering into server internals.
- Use Turbo Intruder for scripted orchestration: retries, staggered releases, and large batches.
- Leverage Burp Suite parallel features for fast iteration, then move to scripts for precision and scale.
- Review example templates and tune engine selection and gate management before large runs.
Keep reading new research, share findings, and rebuild tests after patches. This steady practice helps spot emerging techniques and prevents repeat condition exploits in production.
Conclusion
Practical labs and modern tooling prove that precise timing turns theoretical bugs into repeatable issues. Small timing gaps let parallel requests collide and change intended outcomes in live systems.
Summary: modern guides show attackers align requests with last-byte sync and single-packet techniques to force overlapping work. These patterns make a hidden race condition visible and reproducible.
Defend by making critical updates atomic, enforcing serialization, and adding targeted concurrency tests to CI. Validate core assumptions in code and trace backend data to prove fixes.
Adopt a research-informed mindset: practice in labs, refine tools, and fold lessons into secure code reviews. Treat timing risks as a first-order design concern and keep testing order, time, and state as architectures evolve.