Race Condition

Race Condition is a vulnerability that occurs when the behavior of software depends on the sequence or timing of uncontrolled events. In web applications, attackers exploit the window between a security check and the use of the checked resource to bypass controls or corrupt data.

How It Works

Race conditions occur when multiple operations that should be atomic are instead executed as separate steps. An attacker sends concurrent requests that interleave, causing the application to enter an inconsistent state.

Common Vulnerability Patterns

Time-of-Check to Time-of-Use (TOCTOU)

// Vulnerable: Check and action are separate operations
balance = get_balance(user)          // Thread 1: balance = 100
if balance >= amount:                // Thread 1: 100 >= 100 ✓
    balance = get_balance(user)      // Thread 2: balance = 100
    if balance >= amount:            // Thread 2: 100 >= 100 ✓
        deduct_balance(user, amount) // Thread 1: balance = 0
        deduct_balance(user, amount) // Thread 2: balance = -100!

Coupon/Voucher Double-Spend

// Vulnerable redemption flow
1. Check if coupon is unused
2. Apply discount to order
3. Mark coupon as used

// Attack: Send multiple concurrent requests
// All pass check (step 1) before any reach step 3

Attack Techniques

  • Parallel Requests: Send many requests simultaneously
  • Last-Byte Sync: Hold requests until ready, release simultaneously
  • Single-Packet Attack: HTTP/2 multiplexing to send requests in one TCP packet

Example: Turbo Intruder (Burp Extension)

# Race condition with parallel requests
def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                          concurrentConnections=30,
                          requestsPerConnection=100,
                          pipeline=False)
    for i in range(30):
        engine.queue(target.req, gate='race1')
    engine.openGate('race1')  # Release all at once

Vulnerable Operations

  • Balance transfers and payments
  • Coupon/promo code redemption
  • Voting/rating systems
  • Invitation/referral rewards
  • File uploads with duplicate checks
  • Account linking operations

Prevention

  • Database Transactions: Use atomic operations with proper isolation levels
  • Pessimistic Locking: SELECT ... FOR UPDATE in SQL
  • Optimistic Locking: Version columns with conditional updates
  • Idempotency Keys: Require unique key per operation
  • Distributed Locks: Redis/database locks for critical sections

Prevention Example

-- PostgreSQL: Atomic coupon redemption
UPDATE coupons
SET used = true, used_by = $user_id, used_at = NOW()
WHERE code = $code AND used = false
RETURNING *;
-- Only one request succeeds; others get no rows

See Also