基于短信验证码的安全漏洞

平时测试时,看到下面短信验证码你能够想到什么漏洞测试思路?

image-20230527111409518

验证码的安全问题一直都是逻辑漏洞领域的一大话题,当前的验证码主要分为两类,一是“短信验证码”,一个是”图片验证码“,当然还有谷歌的图片点击等各种各样的验证码,但目前主流的验证码还是这两个。

目前,短信验证码的安全包含了下面的这几个方面,这也是我测短信验证码漏洞的主要方向

  • 暴力生成(短信爆破)
  • 暴力破解
  • 暴力生成破解
  • 内容伪造
  • 服务端回显
  • 绑定关系失效
  • 统一初始化

这里就是我能想到的常规的短信验证码漏洞,也可能还有其他姿势

本篇文章我们就用这几个漏洞来讨论短信验证码的安全性问题

一、暴力生成

暴力生成通俗来讲就是短信轰炸,除此之外还有很多名字,短信接口DDos短信验证码无限发送等,都是它。

指的就是开发者对短信验证功能点的发送短信次数没有限制,或者限制不严,导致攻击者可以利用该漏洞对任意手机号无限发送短信,使目标手机持续收到提醒,造成短信轰炸。由于网站发送短信是需要购买短信资源池的,所以在影响目标的同时造成网站的损失。

那么有人会问了,那该如何挖掘或者测试目标有没有这种漏洞呢?流程如下

  • 先填写你自己的手机号(为了观察效果)

  • 开启bp抓包,点击发送验证码

  • 将抓到的发送短信的bp包发到repeater(也就是重放模块)

  • 先直接连续点击send观察回显和手机的验证码收取情况

  • 受到限制的话就修改请求包尝试绕过

    • 修改电话号,+86,+特殊符号等
    • 修改请求包的个别参数(如果请求包传递的参数除了电话号还有其他的)

来看一个案例,某个短信验证发起短信的请求包如下:

image-20230531160729891

可以看到这里传输的参数除了mobile(电话)之外还有一个smsType,而这里是有限制一分钟只能发一次,但是经过测试,修改smsType参数的值,就可以绕过这个限制。

image-20230531161356247

思考一下这是什么原因?因为smsType代表短信类型,有可能这个短信是用于登录验证,有一个smsType,而另一个地方用于注册,也需要短信验证码,所以也需要一个短信验证码类型(如果需要短信验证码不同的话),简单来说就是下面这样

image-20230531162255785

而他有可能限制你在注册时一分钟只用接收一个验证码,其他的地方没限制,所以可以通过修改这个smsType参数,这个参数也是非常经典的。

但现在很多厂商已经把验证码做成一样了,比如京东,什么操作的验证码都是一样的类型

image-20230531162640848

所以此时发送验证码时的可控参数只有电话号,这时候只能测测改改电话号,或者尝试下面这些方法

同时针对这一问题的防御方法也很简单,只需要限制灭每个手机号一个时间段内能发送短信的最大次数即可,比如限制一分钟一次的同时,给每个手机号限制一天最多10次,这样,即使绕过了一分钟限制,也绕不过10次的限制

二、暴力破解

短信验证码通常是4位或者6位数字,这也给攻击者爆破带来了可能性,要知道一台普通计算机破解6位数字((也就是100万个请求),只需要不到1h的时间,更不用说采用分布式来大规模破解了,因此,如果网站对验证码接口不做限制的话,就很可能存在暴力破解的漏洞

image-20230531172026425

这个防御就更简单了,设置最大错误次数,比如错了几次就不让你登录了,3~5次即可

三、暴力生成破解

​ 有这样一种场景:网站虽然在验证码验证接口设置了最大错误阈值,但是,缺忽略了暴力生成漏洞,也就是短信轰炸漏洞,导致短信验证码可以被无限生成,是否一样会存在被暴力破解导致攻击者获取争取验证码的风险呢?
​ 没错,在这种场景下,攻击者可以使用暴力生成破解的方法,虽然每个验证码只可以验证一次或几次,但是可以无限生成,攻击者每生成1次就破解1次即可绕过验证次数的限制了
​ 这样的场景也给我们带来了一些启发:攻防对抗是多因子对抗,在考虑一种防御方法的同时也要考虑其他因子带来的干扰,避免刻舟求剑,墨守成规。

四、内容伪造

​ 运营商提供短信验证码发送接口时,通常会开放验证码内容的编辑模板,而一些网站,会将验证码内容也作为用户提交的参数进行接收和变更。这样一来,攻击者就可以自定义短信发送的内容。利用自定义的内容来对网站用户批量发送,甚至还可以用来做钓鱼攻击。

image-20230531164700187

某公司的用户找回密码的验证码发送接口存在内容伪造漏洞,验证码默认的内容为:

​ “【xx 公司】您正在重置登录密码,短信验证码是:406798。”攻击者通过修改短信模板,将内容变为:“【xx公司】由于本行系统升级,请您编辑短信发送到:133xxxx1111,短信内容:XX+客户编号,您的临时客户编号是:406798。”
​ 受害者如果看到该短信,信以为真,就会将自己的重置密码验证码发送给到攻击者手机,攻击者就可以修改受害者在网站上的登录密码,以受害者的身份信息进行登录了。
​ 在实际测试中,可通过观察发送短信时,请求包内容是否包含接收短信中的内容来进行判断。若包含,则可以进一步修改短信内容,观察收到的短信内容是否受到影响,来判断漏洞点的存在与否。

五、服务端回显

服务端回显短信验证码马是十分常见的一种漏洞,网站开发人员可能为了调试的方便,有时会将短信验证码发送的数字回显在发送成功的响应报文,也就是bp抓包的回显包。

image-20230531171631722

由于短信发送接口大多数都采用AJAX架构涉及,发送成功时用户界面正常只能看到“发送成功”的字样,并不会把验证码信息显示出来(正经人谁抓包),所以此时攻击者就可以抓包直接获取短信验证码。

image-20230531171649031

看似平平无奇的一个打印操作,带来的后果却是十分严重的。

六、绑定关系失效

​ 短信验证码失效是指短信验证码原本需要与手机号进行绑起,而在验证环节并没有验证验证手机号绑定关系,形成漏洞。
​ 该漏洞表现为:当攻击者发送验证短信时使用自己的手机号进行发送,而在提交验证码时,从数据包中篡改手机号信息,从而使用其他手机号完成注册、登录或绑定等,简单来说就是用自己的电话号注册任意用户,形成任意手机号注册或登录漏洞

image-20230531171114532

该漏洞形成的原因一般有以下几种。

  • 1)服务器将验证码与Session绑定,而未与发送短信时的手机号进行绑定,或只在前端限制手机号不可修改。

  • 2)服务器最终提交的接口中允许有两个手机号字段:验证码对应的验证手机号、用户实际提交的希望注册或绑定的手机号。两个字段不一致,但服务器并未校验。此时输入自己手机收到的验证码并点击提交抓包

    • 把电话末尾加逗号,再跟一个电话,看能否同时注册两个
    • 比如账户参数是mobile,则再写一个mobile参数并传第二个手机号
  • 3)服务端在Session中保存所发送手机号的记录,但攻击者通过覆盖发送记录的方法绕过。

对于该漏洞的防御,需要在判断用户提交的短信验证码时,严格校验该验证码发送时所对应的手机号,在用户提交其他参数时也应当校验参数中的手机号字段与验证手机号是否一致。

七、统一初始化

​ 统一初始化短信验证码是指短信验证码存在默认值,当一个手机号从未发送过短信验证码时直接验证可使用如“000000”“null”“none”“0”等字段进行校验。
​ 该漏洞是由于开发人员在数据库初始化时为验证码字段设置默认值导致的。另外一种情况,对于一些有测试环境的应用,开发人员为了调试方便往往使用较为简单的短信验证码,如“123456”“000000”。当迁移到生产环境后,忘记对数据库中的验证码字段进行删除。

​ 测试时,可以先使用BurpSuite 拦截发送验证码的请求,然后使用“000000”“0”等可能的初始化值进行提交判断。
​ 测试该漏洞时,可利用“smscode=”来提交一个值为空的数据(smscode 代指当前网站短信验证码参数的名称,需要结合实际情况进行修改)。
​ 防御该漏洞,需要避免将测试数据带入到生产环境,不设置统一的初始化验证码。并且,为每次接收短信验证码的手机修改状态,在用户提交验证校验码是否正确的请求时,判断该手机号是否已进行发送验证码的流程,若从未发送过验证码,网站应当返回验证失败。

八、随意验证码

获取验证码之后随意填写,只要位数对就行,说白了就是开发层面没有进行校验验证码是否正确、