Web

Race Conditions

Race condition exploitation: limit overrun (coupon/vote/balance abuse), time-of-check to time-of-use (TOCTOU), single-packet attack technique, Turbo Intruder setup for parallel requests, and Burp Repeater parallel groups.

What are Race Conditions

A race condition occurs when the outcome depends on the timing of multiple operations. In web apps, if a server checks a condition then acts on it in two separate steps — and an attacker sends many requests simultaneously — multiple requests can pass the check before any of them triggers the action. Classic result: spending a one-time coupon multiple times, withdrawing more than a balance, voting multiple times.


Types of Race Conditions

TypeDescriptionExample
Limit overrunBypass a one-time or max-count restrictionUse discount code 10 times
TOCTOUState changes between check and useFile validated, then replaced before processing
Multi-step sequence flawTwo actions must happen in order; race skips the checkConfirm email before buy; skip confirm
Partial constructionObject partially initialised and usable during setupRegister flow — user exists but has no role yet

Detection

Look for state-changing endpoints with limits

In Burp Proxy history, identify:

  • Single-use tokens / codes (vouchers, reset tokens, email verify)
  • Rate-limited actions (login, vote, like, purchase)
  • Balance-dependent actions (transfer, withdraw, redeem)
  • Sequenced multi-step flows (verify → approve → action)

Test with two parallel requests

In Burp Repeater:

  1. Send the target request once to confirm it works.
  2. Add it to a Repeater group (right-click → Add to group).
  3. Duplicate the tab 10–20 times.
  4. Select Send group in parallel (the dropdown next to Send).

If you get multiple 200 OK / success responses where only one should succeed → vulnerable.


Single-Packet Attack (HTTP/2)

The most reliable technique. HTTP/2 multiplexes multiple requests over one TCP connection. By sending them in a single packet, they arrive at the server simultaneously — eliminating network jitter.

In Burp Repeater:

  1. Switch connection to HTTP/2 (Repeater menu).
  2. Group your parallel requests.
  3. Send group in parallel (single-packet attack) — this sends all requests in one HTTP/2 frame.

HTTP/1.1 equivalent (last-byte sync): hold back the last byte of each request, then send all final bytes simultaneously using Turbo Intruder.


Turbo Intruder — Parallel Attack Setup

Install Turbo Intruder from BApp Store.

Send the target request to Turbo Intruder (right-click → Extensions → Turbo Intruder → Send to Turbo Intruder).

Use the race_single_packet_attack.py template:

def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=1,
                           engine=Engine.BURP2)

    # Queue 20 identical requests
    for i in range(20):
        engine.queue(target.req)

def handleResponse(req, interesting):
    table.add(req)

Click Attack. All 20 requests are sent in one HTTP/2 packet.


Exploit: Limit Overrun (Gift Card / Coupon)

Classic pattern — the app checks: “Is this coupon valid and unused?” then marks it used in a second DB write. Race the check:

  1. Identify the redemption request in Proxy.
  2. Send to Repeater, duplicate 15-20 times, group them.
  3. Send group in parallel (single-packet attack).
  4. Check how many responses show a success / discount applied.

If more than one succeeds → the coupon was redeemed multiple times.


Exploit: Balance / Withdrawal Limit Overrun

POST /transfer HTTP/1.1
Host: TARGET
Cookie: session=YOUR_SESSION
Content-Type: application/json

{"amount": 1000, "to": "attacker_account"}

Race 10 identical transfer requests simultaneously. If the balance check and debit are not atomic, multiple transfers can pass the balance check before any of them deducts.


Exploit: TOCTOU — File Upload Validation

App pattern:

  1. Upload a file → validate (check for PHP in it) → if clean, move to final location.
  2. Race condition: upload PHP webshell and access it in the brief window between upload and validation.
# Terminal 1: upload the shell repeatedly
while true; do
  curl -s -X POST https://TARGET/upload \
    -F "file=@shell.php" \
    -b "session=SESSION"
done &

# Terminal 2: access it in the temp location
while true; do
  curl -s https://TARGET/uploads/tmp/shell.php?cmd=id
done

Exploit: Multi-Endpoint Race (Partial Construction)

Some objects are partially valid between creation and the final write. Example: a user is created in DB with a null role, then the role is set in a second query. Race a privileged action in that window:

  1. Trigger account creation.
  2. Simultaneously send requests that require a role check.
  3. If one of them lands between the two DB writes → executes with undefined/default/admin role.

Exploit: Email Verification Bypass

If the flow is: register → verify email → gain access, and the verification token is checked but the account isn’t locked until after:

  1. Register with your email.
  2. Get the verification token.
  3. Race: submit the token AND simultaneously submit a token for a different action (e.g. change email to victim@target.com).

If the token check and the email write are not atomic → you verify a different email than the one the token was issued for.


Burp Suite workflow

  1. Proxy — identify limit-enforced or single-use endpoints.
  2. Repeater — group identical requests, use Send group in parallel (single-packet attack) over HTTP/2.
  3. Turbo Intruder — for larger-scale attacks (50–500 concurrent); use race_single_packet_attack.py.
  4. Inspector — watch response times and lengths to detect winner/loser patterns.
  5. Vary the number of concurrent requests — start with 20, increase if the race window is narrow.