找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2328

积分

1

好友

321

主题
发表于 2025-12-30 07:08:28 | 查看: 25| 回复: 0

在一次安全测试中,目标网站的验证码发送接口引起了我的注意。网站整体防护看起来比较宽松,于是我决定重点审计其验证码机制。

正常的响应与防护

首先,查看一个正常的验证码请求响应。

正常验证码请求与响应
图1:正常发送验证码请求的成功响应

当我们尝试短时间内重复发送验证码时,系统会进行拦截,提示“请勿重复发送,请稍后再试”。

重复请求被拦截
图2:重复发送请求被后端防护逻辑拦截

尝试常规绕过手法

接下来,我尝试使用一些常规的绕过手法来突破这个频率限制。

1. 换行符 – 失败
在参数中添加换行符,尝试干扰后端解析,但请求依然被识别为重复。

换行符绕过失败

2. 添加空格或加号 – 失败
尝试在手机号参数中添加空格或 + 号进行混淆。

body=contact%3D%2013888888888%20%26type%3Dgetverifycode%26cmd%3D-1&data=&yzm=&encrypt=false
body=contact%3D+13888888888%26type%3Dgetverifycode%26cmd%3D-1&data=&yzm=&encrypt=false

结果均显示“请勿重复发送”。

空格与加号绕过失败
图3:添加空格的请求被拦截

加号绕过失败
图4:添加加号的请求同样被拦截

3. 添加分号或逗号 – 失败
尝试使用分号或逗号分割多个手机号,但后端直接返回了“手机号/邮箱格式错误”,说明参数校验在前。

分号与逗号绕过失败
图5:添加分号导致参数校验失败

4. 添加国际区号 – 失败
尝试在手机号前添加 +8686,请求直接返回“验证码发送失败”。

添加区号失败

突破点:利用数据库空白字符

常见思路都失败后,我思考是否可以利用数据库层面的空白字符(如NULL,即 %00)进行干扰。在Burp Suite的Intruder模块中,我在手机号参数后添加 %00 进行爆破测试。

使用NULL字符进行爆破
图6:在Intruder中使用Payload 13888888888%00 进行测试

令人意外的是,这次测试竟然收到了多条验证码短信!

收到多条验证码短信
图7:测试手机收到了多个不同的验证码

为了进一步确认,我将攻击线程数提高到30并再次运行。

设置高并发线程
图8:将Intruder的线程数设置为30

高并发请求结果
图9:部分请求返回成功状态码(447),部分被拦截(408)

问题显现了。按照之前的逻辑,使用 %00 只是改变了参数值,服务器应将其视为同一个手机号的重复请求并进行拦截。但现在却出现了部分请求成功发送验证码的情况,这表明确实存在业务逻辑上的漏洞。

漏洞分析与定位:是条件竞争吗?

最初,我怀疑这是高并发导致的漏洞。查阅资料后,我发现典型的高并发漏洞通常涉及“检查”与“操作”两个步骤的非原子性。

高并发漏洞原理示例
图10:高并发漏洞常见于“先查询后写入”的非原子操作

随后,我与团队的经验丰富的安全工程师交流,他给出了关键提示:这很可能是一个条件竞争漏洞。虽然我过去更多地在文件上传场景中接触条件竞争,但验证码发送的逻辑同样可能存在“判断是否可发送”与“执行发送并标记”之间的时间窗口。如果这两个操作不是原子性的,在高并发请求下,多个线程可能同时通过“检查”,然后都执行了“发送”操作。

那么,如何验证这就是条件竞争?最直接的证明就是:不使用任何混淆技巧,直接重放同一个合法的验证码请求包,通过高并发线程进行轰炸。

准备重放原始请求包
图11:捕获一个正常的验证码请求包用于重放测试

我将重放攻击的线程数设置为50。

设置50线程进行重放攻击

50线程重放攻击结果
图12:大量并发重放请求,部分成功(447),部分被拦截(408)

最终,手机再次收到了多条验证码。

重放攻击成功收到多条验证码
图13:通过纯重放攻击,同样触发了多次验证码发送

这成功验证了漏洞的存在。测试的目的是验证问题,因此无需将线程开得过大以致影响网站正常服务。

总结与思考

  1. 验证码机制同样存在条件竞争漏洞。本次实战表明,不仅是文件上传,任何包含“状态检查”与“状态更新”两步非原子操作的业务逻辑(如发送短信、发放优惠券、扣除余额等),在并发环境下都可能存在竞争条件。
  2. 漏洞挖掘需要理解底层逻辑。从尝试各种绕过手法到最终定位为条件竞争,整个过程要求测试者不仅要“知道怎么操作”,更要思考“为什么会这样”。理解服务器大致的处理流程(检查频率→发送短信→记录发送状态)是推断漏洞成因的关键。
  3. 关于漏洞名称的讨论:有观点认为,这种因高并发导致多个请求绕过限制的情况,本质上就是条件竞争(Race Condition)。因为多个线程(请求)在“竞争”通过检查的时间窗口,先通过检查的线程会执行操作并改变状态,从而影响后续线程的判断。

关于条件竞争漏洞的讨论
图14:与同行探讨漏洞原理,加深理解

这次经历拓宽了我对条件竞争漏洞应用场景的认识。安全测试永无止境,保持好奇与钻研精神才能不断进步。

学习进步过程
图15:技术积累就像充电,需要一步步来

希望这个案例能为你带来启发。欢迎在云栈社区与更多安全爱好者交流技术心得。




上一篇:面向Haskell开发者的TypeScript类型系统对比指南
下一篇:大模型算法工程师职业抉择:同时手握字节、腾讯、蚂蚁三份Offer如何选?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-10 18:32 , Processed in 0.208534 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表