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.
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.
// 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!
// 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
# 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
-- 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