某网站的短信验证码校验漏洞

前言

该网站的登录页面出于安全考虑,添加了每次登录需获取验证码的安全验证机制。然而,正是这个安全验证功能,反而引入了另一个漏洞:验证码获取功能未实现完整的手机号验证,导致系统会向任意手机号发送验证码。

众所周知,每条验证码的发送成本约为3分钱。我们可以简单估算一下风险:

  1. 目前网站仅对同一手机号设置了1分钟内限发1次的限制;
  2. 若批量生成不同手机号发送,仅有约5秒的操作间隔限制;
  3. 按60秒计算,单线程至少可发送12条验证码;
  4. 若使用TURBO等并发工具(未经实测),或多开burp等工具,预估每分钟可发送100-500条。

按此计算:

  • 每分钟造成约15元损失
  • 24小时持续攻击将导致约2.3万元损失

这个漏洞与直接经济损失的关联显而易见。更严重的是,若该接口被提供给"呼死你"等黑产组织:

  1. 可能成为黑产的帮凶
  2. 将造成更巨大的经济损失

漏洞成因分析

该网站本身在明面上并没有直接的漏洞,问题源于开发阶段的设计疏忽。其短信发送流程原本应包含严格的安全验证,但由于逻辑缺陷,攻击者可以绕过关键校验步骤。

正常业务流程

  1. 手机号验证接口 (/sys/checkMobileRegistered)
    • 前端先请求该接口,检查手机号是否已注册(data: false 表示未注册,data: true 表示已注册)。
  2. 后续验证流程
    • 若手机号未注册(data: false),则不允许发送验证码。
    • 若已注册(data: true),则进入密码及验证码校验阶段。
{"code":1,"status":200,"msg":"success","data":false}

漏洞利用方式

  1. 篡改响应包绕过校验
    • 攻击者可通过拦截请求(如 Burp Suite),修改 /sys/checkMobileRegistered 接口的响应包,将 data: false 改为 data: true,从而绕过手机号注册状态检查。
  2. 直接调用短信接口 (/api/message/dingTaskGsUser/getVerificationCode)
    • 该接口仅依赖 mobilephone 参数,无需其他校验。
    • 一旦绕过 /sys/checkMobileRegistered 检查,即可直接构造请求,向任意手机号发送验证码。

漏洞危害

  • 无需复杂挖掘:整个利用过程简单,仅需篡改一次响应包即可绕过关键校验。
  • 批量攻击风险:攻击者可自动化发送大量短信,造成巨额资损(如之前计算的每分钟 15 元,全天 2.3 万元)。
  • 潜在黑产利用:该漏洞可能被“呼死你”等黑产工具滥用,进一步放大危害。

点击证实漏洞