以往,遇到验证码,测试爆破都是重发几次,如果有次数限制大家就不会继续挖了,其实还有个方法可以尝试,我已经通过这个方法得到不少赏金,希望思路对大家有用。
验证码认证分为两个步骤:
- 请求验证码
- 校验验证码
一般常见的验证码爆破就是在第二个校验阶段进行的,一般防护都会对校验次数进行验证,错误一定次数后验证码失效(tips:有时候它显示失效了,实际上还是可以用的 🤣 )
其实还有一种新姿势,不说想到的人不多,但是一说出来你立刻就懂了。
姿势
方法很简单,如果步骤二的校验存在次数限制,此时我们只需要重新发一次验证码就可以再次进行爆破了。你肯定会想“验证码不会更新吗?更新了你还怎么爆破!”

其实这个不重要!说是验证码爆破,其实叫验证码碰撞更贴切一点。整体思路就是固定几个验证码,校验验证码可以有几次机会就固定几个,然后不断自动生成验证码,只要生成的验证码正巧中了你固定的那几个验证码,你就成功了。
利用这个方法的核心就是请求验证码,这个需要发送验证码时没有人机验证,或者能绕过人机验证(绕过这个就看大佬们自己的各种神通了),所以能使用这个方法的时候,一般都会有伴生漏洞(定向短信轰炸、横向短信轰炸)

我们计算一下效率,4位数的验证码,有10000种组合,假设每个验证码可以碰撞5次,那么成功率就是5/10000=0.0005,也就是0.05%,平均需要碰撞1/0.05%=2000次,不看网络卡顿的情况,大概也就2000秒,也就是2000/60=33.333333,半个小时作用。实际上一般会比这个快,经过我的多次成功平均时间来看,平均20分钟左右都可以成功。脸超级无敌黑的话就没办法了。

这个方法可以根据实际情况进行自己优化,比如限制每个手机号发送时间1分钟的话,可以准备70个手机号码,循环发送,或者多线程同时给多个手机号发送验证码,同时校验,可以大大增加成功率,减少碰撞时间,还有很多优化方法大佬们肯定比我懂得多,嘿嘿。
实战案例
下面上一个我的实战案例:
某超市的项目,验证码登录逻辑有缺陷,可导致所有通过该方式验证登录的系统受到影响,通过横向爆破的方式登录系统。
通过抓包分析发现该系统的验证码为4位,且每次可以尝试验证码5次,每个IP每天限制发送验证码50+次,且无人机校验机制,因此可以直接通过脚本进行爆破。这个系统的验证阶段不是直接验证手机号和验证码的,而是第一步骤每个手机号发送验证码后会返回一个不同auth_code值,通过这个auth_code值和验证码来进行匹配校验。
脚本逻辑大致如下:

准备大量手机号,分成50个一组,同时对50个手机号发送验证码,获得50个对应的auth_code,然后再对50个auth_code进行第1个验证码尝试,失败了再对下一个验证码尝试,每次可以同时验证50个验证码提高了效率。5次机会用完再切换IP,对下一组手机号发起验证码。以此类推。
成功的概率:4位数验证码有10000种组合,每个手机号可以尝试5次,也就是5/10000100=0.05%,然后每一轮可以测试50个手机号,每轮成功的概率为0.0550=2.5%。这碰撞成功的概率还是挺高的(因为有IP限制,所以我用了地址池,实际大家可以根据实际情况自己更新优化步骤)。
具体步骤如下:
首先正常获取验证码抓包,然后随机输入验证码也抓包

数据包没存,就不放图了,大佬能理解意思就行了
使用自己熟悉的脚本语言编写,主要就是两个函数,一个是多线程发送验证码,一个是多线程校验验证码
# 快速并发请求
def sent_code(http_raw, data_list: list):
# 并发获取返回协程列表
...
return result_list
# 快速并发请求
def sent_code1(http_raw, data_list: list):
# 并发获取返回协程列表
...
return is_success
附上一张成功截图,不到20分钟成功两次

最后任意验证码登录,替换返回包即可登入系统


最后的话
这个姿势技术性不强,核心还是思路,感觉有用的给我点点赞,祝看官师傅天天高危不重复,嘿嘿嘿
