It was a random Monday. Nothing special going on. YouTube decided to recommend me a video about abusing game economy endpoints and I thought — sure, why not, let me see if this works somewhere.

Fifteen minutes later, I had reproduced a race condition on a reward endpoint.

The Setup

The target was a browser-based shooter — the kind of game where in-game currency actually matters if you wanted show off. The game had a free coins endpoint, basically a periodic reward you could claim. Hit the button, get your coins, come back later.

The request was simple:

POST /api/items/free-coins HTTP/2
Host: [redacted]
Authorization: Bearer [token]
Content-Type: application/json

Normal response looked like this:

{
  "message": "You have received 12 coins.",
  "updates": {
    "coins": 439,
    "freeCoinsClaimCount": 1,
    "freePxAvailable": 2
  }
}

One claim. Count goes to 1. Nothing suspicious.

The Vulnerability

The problem is that the check and the write aren't atomic. The server reads your claim count, decides you're eligible, then goes to update it — and those two steps aren't locked together. If you send enough requests at the exact same time, they all pass the eligibility check before any single one has updated the counter.

This is a TOCTOU bug — Time of Check, Time of Use. Classic race condition.

Reproducing It

Burp Suite's Repeater has a "send group in parallel" feature. With HTTP/2, you can multiplex requests over a single connection, meaning they all land on the server nearly simultaneously. I duplicated the request into 20 tabs, same auth token, and hit send.

None

The response:

{
  "message": "You have received 12 coins.",
  "updates": {
    "coins": 451,
    "freeCoinsClaimCount": 2,
    "freePxAvailable": -10
  }
}

Two things. First, freeCoinsClaimCount is 2 — the claim ran twice. Second, freePxAvailable went negative. The server handed out more than it had budgeted for, which confirmed that multiple claims went through in the same window.

That's your smoking gun right there.

Impact

In-game currency here has real tradeable value. At small scale it's a minor annoyance. Automated, looped, and run across multiple accounts it inflates the economy and undermines everything legitimate players earned. And the barrier to entry is basically zero — just a free Burp Suite download and a valid account.

The Fix

Standard remediation for this kind of thing: make the check and the write a single atomic database operation, so there's no window between the two. A Redis lock keyed on user ID works too. Either way, the whole vulnerability lives in that gap — close the gap, close the bug.

Closing Thoughts

The funny part is I wasn't even doing security research. I watched a video, got curious, and it worked first try. Race conditions on reward endpoints are everywhere and almost never tested. If you're poking around any app with economy mechanics, throw a parallel send at the claim endpoint. Takes two minutes and you might be surprised what comes back.