第 80 章 竞态条件与并发漏洞(Race Window)
竞态条件(Race Condition)是"两个操作并发访问同一资源,顺序影响结果"导致的漏洞:TOCTOU、双花、重复兑换、越权并发。它在 Web 逻辑漏洞、内核漏洞、区块链攻击(闪电贷)中都是核心主题。竞态挖掘 = 找"检查与使用之间的时间窗"。
📍 知识点地图 | 主题:竞态漏洞 | 前置:第58章 | 后续:— | 核心概念:TOCTOU、重复兑换、Turbo Intruder、原子性
80.1 竞态漏洞分类学
按资源: 文件(TOCTOU)/ 状态(检查-使用)/ 数据(重复操作)
按场景:
Web 逻辑: 重复兑换/双花/库存超卖/限速绕过
内核: 并发引用计数/锁缺失(第 79 章常见)
区块链: 闪电贷原子性攻击(第 46 章)
桌面/移动: 文件系统竞态(符号链接攻击)
核心模式: TOCTOU(Time-Of-Check-To-Time-Of-Use)
1. 程序检查某条件(有权限/未使用/余额够)
2. 另一个线程在"检查后、使用前"修改了状态
3. 程序按"检查时的状态"继续执行 → 错误操作
80.2 Web 竞态漏洞(最常见的实战目标)
重复兑换(Double-Spend)
场景: 优惠券/积分/兑换码"只能使用一次"
漏洞: 服务端"检查是否已用 → 标记已用"两步不是原子的
攻击: 并发发送 N 个兑换请求 → 全部通过检查 → 兑换 N 次
复现:
1. 抓兑换请求
2. 并发重放(Burp Intruder 并发/Turbo Intruder)
3. 观察是否多次成功
库存超卖
场景: 商品库存 1 件
漏洞: "检查库存 > 0 → 扣库存"非原子
攻击: 并发下单 → 多人都"买"到同一件
余额竞态
场景: 转账/提现
漏洞: "检查余额 → 扣款"非原子
攻击: 并发多次提现 → 都通过余额检查 → 超额提现
限速/验证码绕过
场景: 登录限速/验证码一次性
漏洞: 计数检查非原子
攻击: 并发爆破绕过限速
80.3 竞态挖掘方法论
1. 找"检查-使用"模式:
□ 读状态 → 判断 → 写状态(三步)
□ 判断和写在不同的请求/函数/锁之外
2. 找"幂等缺失":
□ 重复执行同一请求是否产生多次效果(兑换/转账/创建)
3. 找"共享可变状态":
□ 全局计数器/用户余额/库存/状态字段
工具:
Turbo Intruder(Burp 扩展,并发神器)
racepwn(竞态测试专用工具)
自写 Python(线程池并发请求)
80.4 并发测试实操(Turbo Intruder)
# Turbo Intruder 模板(并发重放)
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=20,
requestsPerConnection=1)
for i in range(100): # 100 并发
engine.queue(target.req, i)
def handleResponse(req, interesting):
if req.status != 200:
table.add(req)
复现流程:
1. 正常请求抓包 → 标记竞态候选
2. Turbo Intruder 并发重放(100-500 并发)
3. 观察: 多次成功? 状态变化异常?
4. 验证: 重复兑换/超卖/绕过生效
80.5 竞态漏洞的根因与防御(分析视角)
根因模式:
□ 非原子操作(检查与使用分离)
□ 缺锁/锁范围错误
□ 数据库事务隔离级别不当
□ 缓存与数据库不一致
□ 单例状态(进程内计数器多实例失效)
防御:
□ 原子操作(数据库 UPDATE 条件扣减/唯一约束)
□ 乐观锁/悲观锁
□ 事务隔离(串行化)
□ 幂等设计(请求 ID 去重)
□ 服务端一次性令牌(不可重放)
80.6 内核/区块链竞态(延伸)
内核: 并发访问共享结构(锁缺失 → UAF/双重释放)
→ 第 79 章利用链常包含竞态原语
区块链: 闪电贷(原子借-攻-还,第 46 章)
→ 组合多个交易的"原子性"攻击
80.7 竞态测试检查清单
□ 功能盘点: 兑换/转账/下单/验证码/状态修改
□ 找检查-使用模式(非原子)
□ 并发重放(Turbo Intruder)
□ 多次成功验证
□ 影响评估(重复兑换/超卖/绕过)
□ 根因确认(哪一步非原子)
□ 报告: 复现(并发数/请求)可重复
动手练习
- 在一个练习应用(或靶场)复现"重复兑换":正常兑换 + 100 并发重放对比。
- 用 Turbo Intruder 对一个验证码功能做并发测试,观察是否绕过一次性。
- 分析一个真实的竞态漏洞报告(SRC 公开披露),指出它的"检查-使用"分离点。
- 讨论题:为什么"数据库扣减用 UPDATE ... WHERE 条件"能防超卖?(原子性)
深入阅读
- 仓库:
CTF-Sandbox-Orchestrator/competition-race-condition-state-drift/(竞态 CTF 子技能) - 仓库:
CTF-Sandbox-Orchestrator/competition-queue-worker-drift/(队列/worker 状态漂移) - 仓库:
skills/api-security/SKILL.md(API 逻辑测试) - 仓库:
skills/pwn-chain/references/kernel-pwn.md(内核竞态) - 实战案例:
skills/field-journal/2026-05-26_pentest-newapi-rate-limit-bypass.md(限速绕过)