====== BBC Ch 12: Race Conditions ====== //Source: Bug Bounty Bootcamp by Vickie Li// ===== How Race Conditions Work ===== A race condition occurs when the security of a system depends on the sequence or timing of events, and that sequence can be disrupted by an attacker. Web applications are particularly vulnerable when they perform a check-then-act sequence without atomic locking: the state can change between the check and the act. The classic pattern is **time-of-check/time-of-use (TOCTOU)**: - Application reads current state (check) - Application performs action based on that state (use) - If two requests execute concurrently, both may pass the check before either completes the use, leading to double-execution ===== Example: Bank Transfer Double-Spend ===== Account has $500. Transfer $500 to account A, and simultaneously (before the first transfer completes) transfer $500 to account B: - Thread 1: checks balance -> $500, OK to proceed - Thread 2: checks balance -> $500 (first transfer not yet committed), OK to proceed - Thread 1: deducts $500, sends to account A - Thread 2: deducts $500, sends to account B - Balance is now -$500; $1000 was sent from a $500 account ===== Example: Coupon/Vote Manipulation ===== An application allows a coupon code to be applied once. If the "check used" and "mark used" steps are not atomic: - Thread 1: checks -- not used -> OK - Thread 2: checks -- not used -> OK (mark not yet written) - Thread 1: applies discount, marks used - Thread 2: applies discount, marks used Both threads succeed and the coupon is applied twice. The same logic applies to vote-once checks, daily limit checks, and inventory reservation. ===== Prevention ===== * **Atomic database operations** -- use transactions with proper isolation levels so that check and update happen as a single atomic unit * **Resource locks** -- acquire a lock on the resource before checking; release after the update; only one thread can hold the lock at a time * **Synchronization** -- language/framework primitives (mutexes, semaphores) to serialize access to the critical section * **Principle of least privilege** -- limit per-account transfer rates, vote limits enforced at the DB constraint level ===== Hunting for Race Conditions ===== ==== Step 1: Find Features with Limits ==== Target any functionality that: * Enforces a numeric limit (one vote, one coupon use, $X transfer limit) * Reads a value then writes a new value in separate operations * Has a critical action gated on a prior state check Examples: * Gift card redemption (single use) * Promotional discount codes * Transfer/withdrawal with a balance check * Daily API rate limits * Poll voting (one vote per user) * Email/SMS confirmation codes (can be used exactly once) ==== Step 2: Send Simultaneous Requests ==== Use curl with the ''&'' operator to fire multiple requests in parallel from the shell: curl -s "https://example.com/api/transfer?to=attacker&amount=500" & curl -s "https://example.com/api/transfer?to=attacker&amount=500" & curl -s "https://example.com/api/transfer?to=attacker&amount=500" & wait For POST requests with a session cookie: for i in $(seq 1 10); do curl -s -X POST https://example.com/api/use_coupon -d "code=SAVE50" -H "Cookie: session=YOUR_SESSION" & done wait The ''&'' sends each request to the background without waiting for the previous to finish. ==== Step 3: Check for Impact ==== After the parallel requests complete, check whether the limit was exceeded: * Was the coupon applied multiple times? Check order history. * Was the vote counted multiple times? Check vote totals. * Did the balance go negative? Check account balance. * Were multiple confirmation codes consumed? Check server-side state. ==== Step 4: Vary Timing and Thread Count ==== Race conditions are timing-sensitive. If the first attempt fails, try: * More simultaneous requests (10, 50, 100) * Requests spread across a slightly longer window * Burp Suite's Turbo Intruder extension (designed for high-concurrency HTTP races) * Python with threading or asyncio for more precise control ===== Escalating the Attack ===== * **Financial double-spend** -- transfer same balance to attacker account twice; redeem gift cards multiple times; use discount codes repeatedly * **Privilege escalation** -- if admin creation or role assignment is gated on a check, race to create two admin accounts simultaneously * **Bypass rate limits** -- if an OTP or password-reset code can be verified multiple times before expiry, race to try more guesses than allowed * **Inventory/resource exhaustion** -- over-claim limited seats, beta invites, or limited-quantity items ===== 5-Step Checklist ===== - Find features that enforce a one-time or limited-count action (coupons, votes, transfers, OTPs). - Understand the check-then-act sequence; identify what window exists between check and commit. - Send simultaneous curl requests (or Turbo Intruder) targeting the limited action. - Check state after requests complete to confirm the limit was exceeded. - Quantify impact: financial loss, unauthorized access, or data corruption and document with a minimal PoC.