对象临时中间状态的条件竞争覆盖
字数 1122 2025-08-10 13:48:27
对象临时中间状态的条件竞争漏洞分析与利用
1. 漏洞概述
条件竞争漏洞中的"对象临时中间状态"是指应用程序在创建或修改对象时,通过多个步骤完成操作,在这些步骤之间存在一个中间状态,攻击者可以利用这个短暂的时间窗口进行恶意操作。
2. 漏洞原理
2.1 典型场景
- 用户注册流程分多个步骤完成
- 数据库操作使用多个SQL语句而非事务
- 框架处理请求时缺乏适当的锁定机制
2.2 关键特征
- 多步操作:对象创建/修改被拆分为多个独立操作
- 无事务保护:操作之间没有原子性保证
- 中间状态暴露:部分完成的对象可以被访问
3. 实验环境分析
3.1 目标系统
- 电子商务网站(SHOP类型)
- 包含用户注册、登录、文章浏览、购买等功能
- 注册需要用户名、邮箱和密码
- 注册后需要邮箱激活
3.2 注册流程分析
- 前端提交注册表单
- 后端在数据库中预注册用户(账户/密码)
- 系统发送激活邮件
- 用户点击邮件中的链接激活账户
- 后端分配权限给用户
- 用户可以正常登录
4. 漏洞发现过程
4.1 初始测试发现
- 同一邮箱可以注册多个不同用户名
- 注册后需要邮箱激活才能登录
- 无法直接使用账号密码登录未激活账户
4.2 关键功能点分析
通过审查JavaScript代码发现关键端点:
const confirmEmail = () => {
const container = document.getElementsByClassName('confirmation')[0];
const parts = window.location.href.split("?");
const query = parts.length == 2 ? parts[1] : "";
const action = query.includes('token') ? query : "";
const form = document.createElement('form');
form.method = 'POST';
form.action = '/confirm?' + action;
const button = document.createElement('button');
button.className = 'button';
button.type = 'submit';
button.textContent = 'Confirm';
form.appendChild(button);
container.appendChild(form);
}
4.3 /confirm端点测试
- 空token被禁止
- 无效token(如"1")返回错误
- 数组参数(如
token[]=)未被禁止
5. 漏洞利用技术
5.1 利用思路
-
注册新用户时,系统执行两个操作:
- 创建用户记录
- 设置API密钥/激活token
-
在两步操作之间,存在用户记录已创建但token未设置的中间状态
-
攻击者可以:
- 发送注册请求
- 立即发送空token的激活请求
- 通过条件竞争绕过邮箱验证
5.2 具体步骤
-
构造注册请求:
POST /register username=attacker&email=victim@example.com&password=123456 -
同时构造激活请求:
POST /confirm?token[]= -
使用工具(如Turbo Intruder)并发发送这些请求
-
成功条件:激活请求在token设置前执行
6. 防御措施
6.1 开发建议
- 使用事务:将相关操作放在一个数据库事务中
- 请求锁定:对关键操作实现请求序列化
- 中间状态保护:确保对象在完全初始化前不可访问
- 参数验证:严格验证输入参数类型和格式
6.2 具体实现
- PHP:使用
session_write_close()确保会话锁定 - 数据库:使用事务(如
BEGIN TRANSACTION...COMMIT) - 框架:利用内置的CSRF保护和请求验证
7. 总结
对象临时中间状态的条件竞争漏洞源于应用程序在处理关键操作时缺乏原子性和适当的锁定机制。通过精心构造的并发请求,攻击者可以利用操作之间的时间差绕过安全控制。防御此类漏洞需要在设计阶段就考虑操作的原子性和状态一致性。