SKILL: Race Conditions — Testing & Exploitation Playbook
SkillDev toolsRace condition and TOCTOU testing for web apps. Use when testing one-time operations, concurrent HTTP abuse, rate-limit bypass, Turbo Intruder gates, HTTP/2 single-packet attacks, and CWE-362-style synchronization gaps.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the SKILL: Race Conditions — Testing & Exploitation Playbook skill
What this skill tells your AI
The instructions your AI receives, as published by langbyyi/cyberstrikeai-src in skills/race-condition/SKILL.md and read by ahel’s review.
AI LOAD INSTRUCTION: Treat race conditions as authorization/state integrity issues: non-atomic read-then-write lets multiple requests observe stale state. Prioritize one-time or balance-like operations. Combine parallel transport (HTTP/1.1 last-byte sync, HTTP/2 single-packet, Turbo Intruder gates) with application evidence (duplicate success responses, inconsistent balances, duplicate ledger rows). Authorized testing only. 中文路由:与「业务流程 / 优惠券 / 库存 / 一次性奖励」相关时,先读本 skill,并交叉加载
business-logic-vulnerabilities。
0. QUICK START — What to Test First
Target endpoints where check and update are unlikely to be a single atomic database operation:
| Priority | Operation class | Example paths / parameters |
|---|---|---|
| 1 | One-time redeem / coupon / bonus | redeem, apply_coupon, claim_reward, voucher |
| 2 | Balance / quota / stock deduction | transfer, purchase, reserve, inventory |
| 3 | Invite / referral / signup bonus | invite_accept, referral_claim |
| 4 | Password / email / MFA verification | verify_token, confirm_email, reset_password |
| 5 | Idempotent-looking APIs without strong keys | POST that should succeed only once per user |
First moves (conceptual):
- Capture the state-changing request in a proxy.
- Send 20–100 copies as simultaneously as your tooling allows.
- Classify outcome: 0/1 expected successes vs N successes or inconsistent final state.
1. CORE CONCEPT
1.1 TOCTOU (Time-of-check to time-of-use)
Thread A Thread B
| |
+-- CHECK (resource OK) |
| +-- CHECK (resource OK) ← both see "OK"
+-- USE / UPDATE |
| +-- USE / UPDATE ← duplicate effect
TOCTOU means the decision (check) and the mutation (use) are not one indivisible step.
1.2 Non-atomic read-then-write
Typical vulnerable pseudo-flow:
balance = SELECT balance FROM accounts WHERE id = ?
if balance >= amount:
UPDATE accounts SET balance = balance - ? WHERE id = ?
Two concurrent requests can both pass the if before either UPDATE commits.
1.3 Database-level vs application-level locking gaps
| Layer | What goes wrong |
|---|---|
| Application | In-memory flag, cache, or session says "not used yet" while DB already updated — or the reverse. |
| ORM / service | Two instances, no distributed lock; each thinks it owns the decision. |
| DB | Missing SELECT … FOR UPDATE, wrong isolation level, or logic split across multiple statements without transaction. |
| API gateway | Per-IP rate limit is check-then-increment — parallel burst passes duplicate checks. |
Hint: UNIQUE constraints and idempotency keys often eliminate entire bug classes — test whether the app enforces them on the hot path.
2. ATTACK PATTERNS
2.1 Limit-overrun (double redeem / double claim)
Send the same authenticated request many times in parallel:
POST /api/v1/rewards/claim HTTP/1.1
Host: target.example
Authorization: Bearer <token>
Content-Type: application/json
{"reward_id":"welcome_bonus"}
Success signal: HTTP 200/201 more than once, duplicate ledger entries, or balance higher than policy allows.
2.2 Rate-limit bypass via simultaneity
If limits are implemented as counters checked per request without atomic increment:
POST /api/v1/login HTTP/1.1
Host: target.example
Content-Type: application/json
{"email":"victim@example.com","password":"wrong"}
Fire N parallel attempts in one wave; compare with N sequential attempts.
Success signal: more failures accepted than documented cap, or lockout never triggers when burst completes inside one window.
2.3 Multi-step exploitation (beat the pipeline)
Workflow: create → pay → confirm. If confirm does not cryptographically bind to pay completion:
- Start two parallel pipelines from the same session/item.
- Complete confirm on channel B while pay on channel A is still in-flight or abandoned.
Success signal: item marked paid/shipped without matching payment, or state skips backward.
3. HTTP/1.1 LAST-BYTE SYNCHRONIZATION
Idea: Hold all requests blocked until every socket has sent the full request except the last byte of the body; then release the final byte together so the server receives them in a tight cluster.
Client 1: [headers + body - 1 byte] ----hold----+
Client 2: [headers + body - 1 byte] ----hold----+--> flush last byte together
Client N: [headers + body - 1 byte] ----hold----+
Why: Reduces network jitter between copies compared to naive sequential paste in Repeater.
Tooling: Custom scripts, some Burp extensions, or Turbo Intruder gate pattern (see §5) as the practical stand-in for synchronized release.
4. HTTP/2 SINGLE-PACKET ATTACK
Idea: Multiplex several complete HTTP/2 streams and coalesce their frames so the first bytes of all requests exit the NIC in one TCP segment (or minimally separated). Receiver-side scheduling then processes them with sub-millisecond spacing.
Burp Repeater (modern workflows):
- Open multiple tabs or select multiple requests.
- Use Send group (parallel) / single-packet attack where available.
- Prefer HTTP/2 to the target if supported.
[ Req A stream ]
[ Req B stream ] --HTTP/2--> one burst --> app worker pool
[ Req C stream ]
Why it often beats HTTP/1.1 last-byte tricks: tighter alignment on the wire; less dependence on per-connection serialization.
5. TURBO INTRUDER TEMPLATES
Repository: PortSwigger/turbo-intruder (Burp Suite extension).
5.1 Template 1 — Same endpoint, gate release
Settings: concurrentConnections=30, requestsPerConnection=30, use a gate so all threads fire together.
Core pattern (repeat N times, then release):
for _ in range(N):
engine.queue(request, gate='race1')
engine.openGate('race1')
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=30,
requestsPerConnection=30,
pipeline=False,
engine=Engine.THREADED,
maxRetriesPerRequest=0
)
for i in range(30):
engine.queue(target.req, gate='race1')
engine.openGate('race1')
def handleResponse(req, interesting):
table.add(req)
Header requirement (unique per queued copy for log correlation; Turbo Intruder payload placeholder):
x-request: %s
Turbo Intruder replaces %s per request when paired with a wordlist (or other payload source) — keep this header on the base request in Repeater before sending to Turbo Intruder. Case-insensitive for HTTP; use a consistent name for log grep.
5.2 Template 2 — Multi-endpoint, same gate
Pattern: One POST to target-1 (state change) plus many GETs to target-2 (read side) released together to widen the TOCTOU window observation.
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=30,
requestsPerConnection=30,
pipeline=False,
engine=Engine.THREADED,
maxRetriesPerRequest=0
)
engine.queue(post_to_target1, gate='race1')
for _ in range(30):
engine.queue(get_target2, gate='race1')
engine.openGate('race1')
Adjust hosts/paths by duplicating RequestEngine instances if endpoints differ (Turbo Intruder supports multiple engines — consult upstream docs for your Burp version).
6. CVE REFERENCE — CVE-2022-4037
CVE-2022-4037 (GitLab CE/EE): race condition leading to verified email address forgery and risk when the product acts as an OAuth identity provider — third-party account linkage/impact scenarios. CWE-362. Demonstrated in public research with HTTP/2 single-packet style timing to win narrow windows.
Takeaway for testers: email verification, OAuth linking, and "confirm ownership" flows are high-value race targets — not only coupons and balances.
References (official / neutral):
- NVD — CVE-2022-4037
- GitLab security advisories and vendor CVE JSON for affected version ranges
7. TOOLS
| Tool | Role |
|---|---|
| PortSwigger/turbo-intruder | High-concurrency replay, gates, scripting in Burp. |
| JavanXD/Raceocat | Race-focused HTTP client patterns (verify compatibility with your stack). |
| nxenon/h2spacex | HTTP/2 low-level / single-packet style experimentation (use responsibly, authorized targets only). |
| Burp Suite — Repeater | Send group (parallel) / single-packet attack for multi-request synchronization. |
8. DECISION TREE
START: state-changing API?
|
NO -----------+---------- YES
| |
stop here one-time / balance / verify?
|
+-------------------------+-------------------------+
| | |
coupon-like rate limit multi-step
| | |
parallel same req parallel vs serial parallel pipelines
| | |
duplicate success? limit exceeded? state mismatch?
/ \ / \ / \
YES NO YES NO YES NO
| | | | | |
report + try HTTP/2 report + try TI report + deepen
evidence single-packet evidence gates per-step
| | | | | |
+----+----+ +----+----+ +----+----+
| | |
tool pick tool pick tool pick
v v v
Burp group / h2spacex TI gates / Raceocat TI + trace IDs
How to confirm (evidence checklist):
- Reproducible duplicate success under parallelism, not flaky single retries.
- Server-side artifact: two rows, two emails, two grants, or wrong final balance.
- Correlate with
x-request(or similar) markers or unique body fields in logs (authorized environments).
中文路由小结:若场景更偏「业务规则 / 定价 / 工作流跳过」,加载 skills/business-logic-vulnerabilities/SKILL.md;本文件专注 并发与传输层同步。
Related
- business-logic-vulnerabilities — workflow, coupon abuse, and logic-first checklists (
../business-logic-vulnerabilities/SKILL.md).
Signals
- GitHub stars
- 115
- Forks
- 4
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
race-condition-langbyyi- Source
- github.com/langbyyi/cyberstrikeai-src