What is a Race Condition
A race condition in discount code validation occurs when multiple simultaneous requests exploit a timing gap between the server verifying the discount code and updating the database, allowing unauthorized repeated use of the code.
ex:
- Redeeming a gift card multiple times
- Rating a product multiple times
- Withdrawing or transferring cash in excess of your account balance
- Reusing a single CAPTCHA solution
- Bypassing an anti-brute-force rate limit
- ... time-of-check to time-of-use (TOCTOU) flaws
Exploitation
# Limit overrun race conditions (Single Step)
## Burp
- Add mutiples request in a group
- Send them has "Send Group (parallel)"
## Turbo Intruder
def queueRequests(target, wordlists): engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=1, engine=Engine.BURP2 ) # queue 20 requests in gate '1' for i in range(20): engine.queue(target.req, gate='1') # send all requests in gate '1' in parallel engine.openGate('1')
---------------------------------------------------------------------------------
# Hidden multi-step sequences (simple)
To detect and exploit hidden multi-step sequences, we recommend the following methodology: PREDICT - PROBE - PROVE
- Is this endpoint security critical?
- Is there any collision potential?
A single request can trigger hidden "sub-states" during processing. Identifying HTTP requests interacting with the same data can expose logic flaws, enabling advanced race condition attacks. For instance, flawed MFA workflows might allow bypassing MFA via forced browsing after the first login step.
EX:
session['userid'] = user.userid ---> With timing, forced browsing can bypass MFA.
if user.mfa_enabled:
session['enforce_mfa'] = True
## Testing clues
- Groups multi-steps sequenece
- Select -> Send group in sequence (separate connections) ---> Calucalue Benchmark
- Select -> Send group in parallel --> Check for clues of deviation
- Understand the issue, eliminate extra requests, and ensure replicability.
---------------------------------------------------------------------------------
# Multi-step (connection warming)
Back-end delays rarely disrupt race conditions, as parallel requests remain synced.
To test endpoint-specific delays, warm connections with a homepage GET in Burp Repeater, then use **Send group in sequence (single connection)**.
If delays persist only on the first request, proceed. Otherwise, use Turbo Intruder to warm connections before attacking.
#~#~#~#~#~#~#~#
Example case (buying object 2 (Don't have enought money))
1. Test if the cart element are tie to the session (Meaning server side, yes)
- Add first item to cart ---> Item we can actually buy (low cost)
----- GROUP TABS
- Add Second item to cart ---> ~300-400ms
- Add process cart (buying) ---> ~70-140ms
- Send group (parallel)
- NOT WORKING, TO MUCH DIFFERENCE BETWEEN TIME
----- GROUP TABS
- Add Home page (Reduce Timing (EWarming Connection)) ---> ~400ms (Warming)
- Add Second item to cart ---> ~70-140ms
- Add process cart (buying) ---> ~70-140ms
- Send group (parallel)
- WORKING, SIMILLAR TIME
---------------------------------------------------------------------------------
# Multi-step (abusing rate or resource limits)
Web servers may delay processing when overloaded. Sending numerous dummy requests can trigger rate limits, creating server-side delays that enable a single-packet attack, even with delayed execution.
---------------------------------------------------------------------------------
# Time-sensitive attacks
Even if race conditions aren't found, precise timing techniques can expose other vulnerabilities. For example, if security tokens use high-resolution timestamps instead of secure random strings, timing two password reset requests for different users could generate identical tokens, compromising security.