Single-Packet Race Condition: Sub-Millisecond Web Exploitation | Tağmaç - root@Tagoletta:~#
Contents

Single-Packet Race Condition: Sub-Millisecond Web Exploitation

Wed May 27 2026 · 4 min read

Category: Security Research

# Attack-Chain# Race-Condition# Exploit


Introduction: Why Classic Race Condition Tests Fail

Race condition vulnerabilities exploit the gap between when an application checks a resource and when it uses it. This class is known as TOCTOU — Time-Of-Check-Time-Of-Use.

The theory sounds simple: send the same request multiple times simultaneously, bypass the check. In practice, network jitter makes this nearly impossible. Two HTTP requests can be separated by 10–50ms due to varying network conditions, while most race condition windows exist for only 2–20ms.

In 2023, James Kettle (PortSwigger) presented the "Smashing the State Machine" research at DEF CON 31, introducing a technique that fundamentally solves this problem: the Single-Packet Attack.

Sub-States: Where the Vulnerability Lives

For a race condition to be exploitable, the application must enter a brief "intermediate state" (sub-state).

Consider a gift card redemption flow:

1. Check balance      →  balance >= 100 ?  ✓
2. [SUB-STATE ~5ms]   →  not yet deducted
3. Deduct balance     →  balance -= 100

If a second request can enter between steps 1 and 3 — while the balance hasn't been deducted yet — the card gets redeemed multiple times.

This window typically exists for 2–20 milliseconds.

The Single-Packet Technique

In the classic approach, each HTTP request travels over its own TCP connection. Network conditions cause requests to arrive at different milliseconds. The window is missed.

The single-packet solution:

HTTP/2 multiplexing allows multiple requests to be packed into a single TCP frame. All requests inside the same frame arrive at the server simultaneously — zero inter-request delay.

Last-frame synchronization:

  1. Prepare N-1 requests, hold them
  2. Prepare the final request
  3. Pack all of them into one TCP frame
  4. Send → all processed concurrently

CVE-2024-58248: nopCommerce Gift Card Race Condition

nopCommerce is a widely deployed open-source e-commerce platform. The gift card redemption endpoint's transaction sequence is not atomic.

Vulnerable code flow (simplified):

// GiftCardService.cs
public async Task<bool> RedeemGiftCard(string code, decimal amount)
{
    var card = await _giftCardRepo.GetByCode(code);

    // STEP 1: Check balance
    if (card.RemainingAmount < amount)
        return false;

    // SUB-STATE EXISTS HERE (~3-8ms)
    // card.RemainingAmount NOT YET updated in DB

    // STEP 2: Deduct
    card.RemainingAmount -= amount;
    await _giftCardRepo.Update(card);
    return true;
}

If multiple concurrent requests pass Step 1 before any of them reaches Step 2, all of them execute the deduction. A $100 gift card can be redeemed multiple times.

Exploit with Burp Suite:

1. Burp Suite → Repeater → Create a new tab group
2. Add the gift card redemption request 5 times to the group
3. Select "Send group (parallel)"
4. Ensure HTTP/2 is enabled for the target
5. Send → If all responses return 200 OK, exploit succeeded

Limit Overrun: Other Attack Scenarios

Race conditions extend far beyond gift cards:

1. Rate limit bypass:

POST /api/send-otp HTTP/2
# 5 requests/minute limit
# Send 5 requests simultaneously
# All processed before counter increments

2. Currency/balance manipulation:

Balance: $50
Send simultaneously: Transfer $40 × 3
Sub-state: all three checks pass ($50 >= $40)
Result: $120 transferred from a $50 balance

3. Single-use tokens:

Send email confirmation token 3 times simultaneously
All three pass before token is marked "used"

Automation with Turbo Intruder

For higher request volume, use Burp's Turbo Intruder extension:

def queueRequests(target, wordlists):
    engine = RequestEngine(
        endpoint=target.endpoint,
        concurrentConnections=1,
        requestsPerConnection=30,
        pipeline=True
    )
    for i in range(30):
        engine.queue(target.req)
    engine.start(timeout=10)

def handleResponse(req, interesting):
    if req.status == 200:
        table.add(req)

Detection

Endpoints likely to contain race conditions:

  • Any endpoint doing multi-step DB operations instead of atomic transactions
  • Balance / credit / point mutation endpoints
  • Single-use resource consumption (tokens, coupons, invite links)
  • Response time anomalies under parallel load

Mitigation

1. Atomic database transactions with row-level locking:

BEGIN TRANSACTION;
SELECT balance FROM gift_cards WHERE code = ? FOR UPDATE;
UPDATE gift_cards
  SET remaining = remaining - ?
  WHERE code = ? AND remaining >= ?;
COMMIT;

2. Mutex / distributed lock:

using (await _lockService.AcquireLock($"giftcard:{code}"))
{
    // Serialized execution — one thread at a time
    await RedeemGiftCard(code, amount);
}

3. Idempotency keys:

Every redemption request must carry a single-use idempotency key. A second request with the same key is automatically rejected without re-executing the logic.

Conclusion

The single-packet technique moved race condition exploitation from theoretical to practical. Sub-millisecond windows are now reliably exploitable.

CVE-2024-58248 proved that this technique can cause significant financial losses in real-world e-commerce platforms. Any "check → use" flow that doesn't use atomic database operations is a potential race condition.


CVE: CVE-2024-58248
Platform: nopCommerce
Researcher: James Kettle / PortSwigger Research
Conference: DEF CON 31 (2023), Black Hat USA 2023
Reference: https://portswigger.net/research/smashing-the-state-machine

Frequently Asked Questions

What is a race condition in web applications?

A flaw where two requests processed concurrently interfere within a small time window — for example redeeming a gift card or withdrawing balance twice before the state updates. It is a time-of-check to time-of-use (TOCTOU) bug.

What is the single-packet attack?

A technique by James Kettle that sends 20–30 requests so they arrive in a single TCP packet, eliminating network jitter and aligning them within sub-millisecond windows to reliably trigger race conditions.

How do you exploit race conditions with Burp Suite?

Burp Repeater's send-group-in-parallel feature uses the single-packet technique automatically; the post walks through exploiting CVE-2024-58248 in nopCommerce this way.

How do you prevent race conditions?

Use database-level locking or atomic transactions, enforce idempotency keys, apply per-resource mutexes, and design state changes to be atomic rather than check-then-act.