scanrub
Concurrent Execution using Shared Resource with Improper Synchronization (_Race Condition_)low prioritypartial coverage

Concurrent Execution using Shared Resource with Improper Synchronization (_Race Condition_)

3 min read 15 reports analyzed ScanRub Research
Share

Summary

This is CWE-362, the general parent category: two or more requests touch the same shared resource - a coupon's redemption count, a wallet balance, a vote tally, an invite's single-use flag - with no locking or serialization between them, so the outcome depends on which request the database or application happens to process first. Sent one at a time, every request behaves correctly. Sent concurrently, a resource meant to be usable exactly once (a discount code, a referral bonus, a free-trial claim) can be consumed multiple times, because each concurrent request reads the "still available" state before any of them has written back the "now used" state. It's one of the few logic-flaw classes that a black-box scanner can genuinely reproduce, since the bug only manifests under real concurrency - there's no payload to inject, only a timing window to create.

◈ flow diagram
Parallel Req…Shared Resou…Check Condit…Time WindowExploit StateInconsistent…
◈ chart
Critical
5
High
6
Medium
3
Low
1

Top Affected Components / Targets

  • Coupon, discount, and voucher redemption endpoints
  • Referral and sign-up bonus claim endpoints
  • Voting, liking, and following actions with an expected one-per-user limit
  • Withdrawal, transfer, and checkout flows touching a balance or inventory count
  • Invite and activation links meant to be single-use

Common Attack Vectors

  • Fire a burst of identical concurrent requests at a single-use action and check whether more than one succeeds
  • Target GET-based state-changing actions (?action=redeem&code=X) discovered during crawling, which are both common in real disclosures and simplest to race without needing a captured multi-field form submission
  • Look specifically at resources with no prior consuming call in the test session - a coupon already "used" earlier in the same run gives every racer a uniform rejection and hides a real race entirely

Common Payloads

  • N concurrent, byte-identical HTTP requests fired against the same URL with no artificial delay between them (the "burst")
  • No injected payload - the race is created by request timing, not request content

Detection Strategy

Fire a burst of N concurrent requests at a state-changing-shaped endpoint with no baseline call beforehand (a baseline request would itself consume a one-shot resource before the race ever starts, hiding the bug). A correctly-serialized single-use endpoint produces exactly one "success" response and N-1 "rejected" responses under concurrency - that's the definition of enforced single use. If two or more requests in the burst report success, the resource was consumed more than once and synchronization failed. The response set needs to resolve into exactly two distinct status groups (a majority-rejected group and a minority-succeeded group) to read cleanly; any other shape means there's no clean single-use signal to interpret, and the endpoint is skipped rather than guessed at.

Tip: Testing tools that run these checks in parallel across every discovered endpoint can cut the time required substantially compared to fully manual testing, as long as they confirm findings with more than one signal to keep the false-positive rate down.

False-Positive Notes

  • Idempotent endpoints, where repeating the same request is always safe and expected to succeed every time, such as re-fetching a resource or re-applying an already-applied setting, will show all-success under a burst and shouldn't be flagged; a clean majority-rejected, minority-succeeded split is what "meant to be single-use" actually looks like under concurrency.
  • Real disclosed races that require a structured POST or form submission (a multi-field checkout, a transfer form) are harder to test this way than simple GET-based redemption links, since replaying a full form submission concurrently needs more setup than replaying a URL.

How to Test

Manual Testing Methodology

Here is a systematic approach to identifying Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition) vulnerabilities in a target application.

Step 1: Reconnaissance and Surface Mapping

Before testing, map all input vectors that could be affected. Identify parameters, headers, cookies, and request bodies that interact with the vulnerable component. A proxy such as Burp Suite or OWASP ZAP, paired with normal browsing of the target, is usually enough to build this list.

Step 2: Baseline Request

Send a legitimate request and record the normal response: status code, content length, response time, and any identifying tokens. This baseline matters because it's what you'll compare later responses against once payloads are involved.

Step 3: Payload Injection

Inject test payloads into each identified input vector one at a time. Start with benign detection payloads before escalating to anything that could actually trigger the vulnerability. For Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition) specifically, fire the target request (coupon redemption, balance withdrawal, unique-resource creation) many times concurrently and near-simultaneously, using a tool designed for precise request timing rather than a simple loop, since network jitter from sequential requests won't reliably open the race window.

Step 4: Response Analysis

Compare the response against your baseline, looking specifically for whether the action that should only succeed once succeeded multiple times — a balance that went negative, a coupon redeemed more times than its limit, or duplicate unique records created from concurrent requests.

Step 5: Confirmation

Once a potential vulnerability is detected, confirm it with at least a few independent test cases to rule out coincidence. Document the exact request and response as proof. For Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition), a confirmed finding typically means showing that attacker-controlled input changes the application's behavior in a way that matters for security, not just that a payload was reflected somewhere harmless.

Real-World Impact

Real-World Impact

Race conditions and time-of-check-to-time-of-use flaws exploit the gap between when an application checks a condition and when it acts on it. In that window, an attacker who can fire multiple concurrent requests can get an action approved multiple times that should only have been possible once — redeeming a coupon repeatedly, withdrawing more balance than exists, or registering the same unique resource twice.

These bugs are notoriously undercounted in manual testing because they're invisible to sequential, one-request-at-a-time testing; the vulnerable window is often only milliseconds wide and only opens up under genuine concurrency.

The financial and business-logic impact tends to be direct and quantifiable — free money, bypassed limits, or duplicated unique state — which is part of why race-condition findings are increasingly well-rewarded in bug bounty programs once demonstrated convincingly.

Prevention & Remediation

Prevention and Secure Coding

Preventing Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition) takes a defense-in-depth approach — no single control below is sufficient alone, but together they close off both the primary path and the most common bypasses.

Atomic operations at the data layer. Use database-level atomic operations — row-level locking, compare-and-swap, unique constraints — for any check-then-act sequence involving shared state, rather than checking in application code and acting in a separate step.

Eliminate the check-then-act pattern where possible. Where the data store can enforce the invariant directly (a unique constraint preventing a duplicate row, a conditional update that only succeeds if a balance is still sufficient), rely on that instead of an application-level check.

Idempotency keys for non-repeatable operations. Require a client-supplied idempotency key for operations like payments or coupon redemption, and reject a repeat of the same key regardless of timing.

Test under real concurrency, not just sequentially. Include concurrent-request test cases (fired via a tool built for precise request timing, not just a for-loop) in the test suite for any endpoint that touches shared, limited, or unique state.

Frequently Asked Questions

What is Concurrent Execution using Shared Resource with Improper Synchronization (_Race Condition_)?
This is CWE-362, the general parent category: two or more requests touch the same shared resource - a coupon's redemption count, a wallet balance, a vote tally, an invite's single-use flag - with no locking or serialization between them, so the outcome depends on which request the database or application happens to process first.
How common is Concurrent Execution using Shared Resource with Improper Synchronization (_Race Condition_) in bug bounty reports?
Scanrub's research corpus for this playbook is built from 15 disclosed HackerOne reports in this category, synthesized for detection and prevention guidance rather than reproduced verbatim.
How do I test for Concurrent Execution using Shared Resource with Improper Synchronization (_Race Condition_)?
Map every input vector, record a baseline response, then inject targeted test payloads one field at a time and compare the response for timing, length, error, or reflection differences from that baseline. The "How to Test" section above walks through the full methodology for this specific vulnerability class.
What is the single most effective fix for Concurrent Execution using Shared Resource with Improper Synchronization (_Race Condition_)?
Enforce check-then-act invariants atomically at the data layer (row locking, compare-and-swap, unique constraints) rather than as a separate check followed by a separate action in application code.
Weekly security research

New vulnerability playbooks, tool updates, and bug bounty insights - delivered to your inbox. No spam.

Unsubscribe anytime. We respect your inbox.
Press ⌘K to search×