2023 Black Hat | 服务器端漏洞篇之条件竞争专题
字数 2429 2025-08-10 16:34:31
服务器端漏洞之条件竞争专题教学文档
一、条件竞争基础概念
1.1 什么是条件竞争
条件竞争是一种与业务逻辑缺陷密切相关的漏洞,当网站在处理同时发来的多个请求时,会出现多个不同线程同时与相同数据交互的情况,导致应用程序出现异常行为。
1.2 竞争窗口
"竞争窗口"指可能发生碰撞的时间段,例如与数据库两次交互之间的几分之一秒。条件竞争的危害与其他逻辑漏洞相似,是与端点密切相关的。
二、条件竞争利用类型
2.1 突破限制
这是条件竞争最知名的利用类型,典型场景包括:
- 多次使用优惠券
- 多次兑换礼品卡
- 对产品进行多次评价
- 提取或转账超过账户余额的现金
- 重复使用单个验证码
- 绕过反暴力破解速率限制
这类攻击属于"time-of-check to time-of-use" (TOCTOU)缺陷的子类型。
2.2 突破限制的典型流程
- 检查用户是否使用过优惠券
- 将折扣应用于购买商品
- 在数据库中将优惠券状态修改为"已使用"
如果在窗口期内(步骤1和步骤3之间)同时发起多个请求,可以突破使用限制。
三、检测和利用条件竞争的工具与技术
3.1 Burp Suite 2023.9+新功能
- 原生支持并发请求
- 自动适应不同HTTP版本:
- HTTP/1:使用末字节(last-byte)同步技术
- HTTP/2:使用单数据包攻击技术(Black Hat USA 2023首次演示)
3.2 使用Burp Repeater
检测和利用步骤:
- 寻找一次性或限制请求速率的端点
- 连续快速多次请求该端点,测试能否突破限制
- 使用"Create tab group"创建请求包组
- 选择"Send group in parallel"并行发送请求
3.3 使用Turbo Intruder
需要满足以下条件:
- 目标支持HTTP/2(单包攻击与HTTP/1不兼容)
- 设置
engine=Engine.BURP2和concurrentConnections=1 - 使用
gate参数对请求分组 - 使用
engine.openGate()发送分组请求
示例脚本:
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2)
# queue 20 requests in gate '1'
for i in range(20):
engine.queue(target.req, gate='1')
# send all requests in gate '1' in parallel
engine.openGate('1')
四、条件竞争高级利用技术
4.1 隐藏的多步骤序列
许多操作背后包含多个隐藏的请求序列,用户只能看到进入序列前和得到响应两个动作,中间过程称为"子状态"。
方法论(来自PortSwigger白皮书)
-
预测潜在的碰撞
- 评估端点安全性重要性
- 判断是否有碰撞可能(需对同一条记录操作)
-
探寻线索
- 进行基准测试("Send group in sequence")
- 使用单数据包攻击测试("Send group in parallel")
- 寻找响应变化或二阶效应
-
证明猜想
- 删除多余请求确保可复现
- 将条件竞争串联看待
4.2 多端点条件竞争
涉及同时向多个端点发送请求的条件竞争,例如:
- 将商品添加到购物车
- 付款
- 在强制浏览到订单确认页面前添加更多商品
对齐竞争窗口的挑战
- 网络架构引入的延迟
- 端点特定处理引入的延迟
解决方案:
- 连接预热:通过无关请求平滑处理时间
- 滥用速率或资源限制:触发服务器端延迟
4.3 单端点条件竞争
向单个端点发送具有不同值的并行请求可能触发条件竞争,例如:
- 密码重置机制中存储用户ID和重置令牌
- 电子邮件确认等基于邮件的操作
4.4 基于会话的锁定机制
某些框架(如PHP)会按顺序处理每个会话的请求,解决方案:
- 使用不同会话令牌发送每个请求
4.5 局部构造条件竞争
多步骤创建对象可能引入可被利用的临时中间状态,例如:
- 注册新用户时先创建用户再设置API密钥
- 使用非标准语法传递数据结构(PHP中的
param[]、Rails中的param[key])
4.6 时间敏感型攻击
利用高分辨率时间戳而非加密安全随机字符串生成安全令牌的场景,例如:
- 仅使用时间戳随机化的密码重置令牌
- 通过并发请求计时判断是否得到相同时间戳生成的令牌
五、防御措施
- 避免混合不同存储位置的数据
- 确保敏感端点状态更改原子化
- 使用单个数据库事务
- 利用数据存储完整性和一致性功能
- 如列唯一性约束
- 不要用一层数据存储保护另一层
- 会话不适合防止数据库限制溢出攻击
- 确保会话处理框架保持内部一致
- 避免单独更新会话变量
- 考虑无状态架构
- 使用JWT等将状态推送到客户端
六、实战案例
6.1 突破限制条件竞争(优惠券滥用)
- 将商品加入购物车
- 拦截"Apply"促销代码请求
- 重复发送20个请求到Repeater
- 创建请求包组并并行发送
- 刷新购物车查看折扣叠加效果
6.2 绕过速率限制
- 将登录请求发送到Turbo Intruder
- 使用内置"race-single-packet-attack.py"模板
- 设置密码字段为变量位(%s)
- 复制密码本到剪贴板
- 执行攻击并发送成功响应到浏览器
6.3 多端点条件竞争(购物车)
- 购物车留一张礼品卡
- 将"添加夹克"和"结算"请求放入Repeater分组
- 并发发送请求
- 检查是否成功低价购买
6.4 单端点条件竞争(邮件确认)
- 准备两个不同邮箱的确认请求
- 确保目标邮箱(carlos@...)在第二个请求
- 并发发送请求
- 检查是否收到目标邮箱的确认邮件
6.5 局部构造条件竞争(注册机制)
- 发现注册仅支持特定域名邮箱
- 测试token参数行为
- 使用空值数组绕过(
token[]=) - 编写Turbo Intruder脚本并发注册和确认请求
- 使用成功注册的账号登录
6.6 时间敏感型攻击(密码重置)
- 并发两个密码重置请求(不同用户名)
- 使用两套独立会话和CSRF token
- 检查是否收到相同重置令牌
- 修改用户名为目标用户完成重置
七、总结
条件竞争是与业务逻辑密切相关的服务器端漏洞,通过精心设计的并发请求可以在竞争窗口期内突破系统限制。Burp Suite 2023.9+提供的单数据包攻击技术大大简化了检测和利用过程。防御这类漏洞需要从架构设计上消除敏感端点的子状态,确保状态更改的原子性。