Hacktricks-skills race-condition-exploitation
How to identify and exploit race condition vulnerabilities in web applications. Use this skill whenever the user mentions race conditions, TOCTOU attacks, concurrent request exploitation, HTTP/2 single-packet attacks, limit-overrun vulnerabilities, hidden substates, or timing-based security bypasses. Also trigger when users want to test for race conditions in authentication flows, payment systems, coupon redemption, email verification, OAuth token generation, or any stateful web application logic.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/race-condition/SKILL.MDRace Condition Exploitation
A skill for identifying and exploiting race condition vulnerabilities in web applications through concurrent request attacks.
When to Use This Skill
Use this skill when:
- Testing for race conditions in web applications
- Exploiting TOCTOU (Time-of-Check-Time-of-Use) vulnerabilities
- Performing limit-overrun attacks (coupon redemption, rate limiting bypass)
- Testing hidden substate vulnerabilities (email verification, account confirmation)
- Exploiting time-sensitive token generation
- Bypassing 2FA through race conditions
- Testing OAuth2 token generation races
- Performing WebSocket race condition attacks
- Any scenario involving concurrent state manipulation
Core Concepts
What is a Race Condition?
A race condition occurs when multiple requests are processed simultaneously, and the application's behavior depends on the order or timing of those requests. The goal is to make requests arrive at the server within less than 1ms of each other to exploit the timing window.
Key Attack Patterns
- Limit-Overrun: Exploit counters/limits (coupons, ratings, withdrawals)
- Hidden Substates: Exploit brief windows where data is partially written
- Time-Sensitive Tokens: Exploit predictable token generation
- Confirmation Bypass: Exploit gaps between write operations
Synchronization Techniques
HTTP/2 Single-Packet Attack
HTTP/2 allows multiple requests over a single TCP connection, reducing network jitter.
Requirements:
- Target must support HTTP/2
- Use Turbo Intruder with
Engine.BURP2 - Gate requests to withhold final bytes
Basic Approach:
- Queue multiple requests with a gate
- Send partial requests (all but last byte)
- Open gate to flush all final bytes simultaneously
- Requests arrive in single packet
HTTP/1.1 Last-Byte Synchronization
For HTTP/1.1 targets, use Nagle's algorithm to batch final frames.
Preparation:
- Send headers and body minus final byte without ending stream
- Pause 100ms after initial send
- Disable TCP_NODELAY to enable Nagle's algorithm
- Ping to warm up connection
- Send withheld frames together
Verification: Use Wireshark to confirm single-packet arrival.
HTTP/3 Last-Frame Synchronization (QUIC)
HTTP/3 uses QUIC (UDP), so TCP coalescing doesn't apply. Use purpose-built libraries.
Requirements:
- Library with QUIC frame control (e.g., H3SpaceX)
- Manipulate stream-final DATA frames (FIN)
- Coalesce into same UDP datagram
Limitations:
- Concurrency bounded by QUIC
parametermax_streams - If low, open multiple H3 connections
- UDP datagram size limits frame count
Attack Methodology
Step 1: Identify Potential Targets
Look for endpoints that:
- Modify server-side persistent data (not client-side)
- Alter existing data (more exploitable than adding new data)
- Use same identifier (username, token, session)
- Have limits or counters (coupons, attempts, ratings)
- Involve multi-step workflows (registration, verification, payment)
High-Value Targets:
- User profile updates
- Password reset flows
- Email verification
- Payment/checkout processes
- Coupon/discount redemption
- Account registration
- OAuth authorization
- 2FA enforcement
Step 2: Initial Probing
Test endpoints with race condition attacks:
- Send 20-50 concurrent requests
- Observe for unexpected responses
- Look for deviations from expected behavior
- Check for negative timestamps in Turbo Intruder (indicates overlap)
Step 3: Refine the Attack
Narrow to minimal requests needed:
- Often just 2 requests suffice
- May require automation due to timing precision
- Test different request counts (10, 50, 100+)
Step 4: Verify Exploitation
Confirm the vulnerability:
- Check if limit was exceeded
- Verify unexpected state changes
- Confirm bypass of security controls
- Document reproducible steps
Common Vulnerability Patterns
Limit-Overrun / TOCTOU
Examples:
- Redeeming gift cards multiple times
- Rating products multiple times
- Withdrawing cash exceeding balance
- Reusing CAPTCHA solutions
- Bypassing rate limits
Attack: Send 50+ identical requests simultaneously to exceed intended limit.
Hidden Substates
Pattern: Two writes to database create brief window where only first write exists.
Example - Account Confirmation Bypass:
- Register account (username + password written)
- Token written separately
- Brief window where token is null
- Send confirmation requests with empty token during window
- Account confirmed without valid token
Attack: Register + send 50 confirmation requests with
token= or token[]=
Time-Sensitive Token Generation
Pattern: Tokens generated from timestamps may be identical for concurrent requests.
Attack:
- Send two password reset requests simultaneously
- Compare tokens
- Matching tokens indicate vulnerability
2FA Bypass
Pattern: Session created before 2FA enforcement flag is set.
Vulnerable Code:
session['userid'] = user.userid if user.mfa_enabled: session['enforce_mfa'] = True # generate and send MFA code
Attack: Send concurrent login requests during session creation window.
OAuth2 Eternal Persistence
Pattern: Multiple AT/RT pairs generated from single authorization code.
Attack:
- Accept OAuth authorization
- Race the authorization_code exchange
- Generate multiple token pairs
- Revoke app access - some tokens remain valid
Tools and Scripts
Turbo Intruder Scripts
Use the bundled scripts in
scripts/:
- HTTP/2 single-packet attackturbo_race_single_packet.py
- Multi-endpoint race conditionturbo_race_multi_endpoint.py
- Limit-overrun attacksturbo_race_limit_overrun.py
Python Scripts
- HTTP/2 race condition testingrace_http2_tester.py
- HTTP/1.1 last-byte synchronizationrace_http1_sync.py
- WebSocket race conditionsrace_websocket_tester.py
Server Architecture Considerations
Connection Warming
Send inconsequential requests first to normalize timing:
# Warm up connection for _ in range(5): requests.get(target_url, verify=False)
Session-Based Locking
Some frameworks serialize requests by session:
- PHP sessions: Use different session tokens per request
- Database locks: May require different user contexts
Rate/Resource Limits
If warming ineffective, trigger server delays:
- Flood with dummy requests
- Induce server-side delays
- Facilitate single-packet arrival
Concurrent Stream Limits
HTTP/2:
SETTINGS_MAX_CONCURRENT_STREAMS
- Apache: 100
- Nginx: 128
- Go: 250
- NodeJS: unlimited
HTTP/3: QUIC
max_streams parameter
- If low, spread race across multiple connections
Advanced Techniques
First-Sequence Sync (IP Fragmentation)
Extends single-packet attack beyond 1,500 bytes to 65,535 bytes:
- Split packet into IP fragments
- Send in different order
- Prevent reassembly until all fragments arrive
- Can send 10,000 requests in ~166ms
See: https://github.com/Ry0taK/first-sequence-sync
WebSocket Race Conditions
Use WebSocket Turbo Intruder:
- Use
engineTHREADED - Spawn multiple WS connections
- Fire payloads in parallel
- Tune thread count for concurrency
Diagnostics
Turbo Intruder Indicators
- Negative timestamps: Server responded before request fully sent (expected in races)
- Response timing: Look for responses arriving before all requests sent
- Status codes: Unexpected codes may indicate race exploitation
Verification Methods
- Wireshark: Confirm single-packet arrival
- Application state: Check if limit exceeded or state changed
- Database: Verify unexpected data states
- Logs: Look for race-related errors
Safety and Ethics
Only test systems you have authorization to test.
- Obtain written permission before testing
- Use in bug bounty programs with clear scope
- Document findings responsibly
- Do not exploit in production without authorization
References
- PortSwigger Research: https://portswigger.net/research/smashing-the-state-machine
- PortSwigger Labs: https://portswigger.net/web-security/race-conditions
- H3SpaceX (HTTP/3): https://pkg.go.dev/github.com/nxenon/h3spacex
- First-Sequence Sync: https://github.com/Ry0taK/first-sequence-sync
- WebSocket Turbo Intruder: https://github.com/d0ge/WebSocketTurboIntruder