接入教程2026-10-30· 11 分钟阅读

短信验证码被刷怎么防:六类攻击、四层防御与接口层的三个坑

短信验证码被刷到一夜五位数账单的原因与防御:六类攻击方式(含最易漏的单号码轰炸)、按性价比排序的四层防御(人机校验/四维频控/风险识别/监控熔断)、验证码设计六个细节,以及接口层三个真实坑——内容必须带签名否则1009、短信通道签名不含tm、业务层重发会与通道自动重发叠加。

诺
诺正通研究院

短信验证码被刷,是少数几个"一夜之间账单变五位数"的技术事故。更麻烦的是,它通常不是漏洞被攻破,而是你的接口被当成免费短信通道用了。

这篇讲清六类攻击怎么打进来、四层防御怎么按成本排队,以及接短信接口时三个真实存在的坑。

一、先看攻击是怎么发生的

一个典型场景:注册页发出验证码,接口带 phone 参数,没有任何前置校验。

攻击者的做法比你想的简单:

  • 一次性导入 3 万个手机号(数据在黑产里是现成的)
  • 循环调用你的验证码接口,每个号发一条
  • 三万个真实用户收到"您的验证码是 123456"
  • 你的账单按条计费,投诉同步涌向运营商
  • 注意一个反直觉的点:攻击者的收益往往不是撞库成功,而是把你变成骚扰短信的发射源——他要的是让这批号码收到短信(比如用来做诈骗前置、给竞争对手制造投诉、或者纯粹消耗你的成本)。

    所以防御的核心目标不是"防破解",是防滥用。

    二、六类攻击方式

    #攻击方式特征主要防线
    1脚本撞库单一 IP 高频请求,号码连续/规律频率控制 + IP 维度
    2短信轰炸针对同一个号码大量请求,让受害者被骚扰手机号维度频控(最容易漏)
    3接码平台(卡商)使用虚拟号段/一人多号完成注册,绕过手机号唯一性号段识别 + 设备指纹 + 业务风控
    4接口逆向直连抓到你的 App 包,直接调你的发送接口,绕过前端全部校验服务端签名 + 渠道校验
    5内部泄露商户密钥流出,攻击者以你的名义发短信密钥分环境 + 轮换 + 调用明细告警
    6人机混合(打码平台)人工/打码服务过图形验证码,再发起请求行为验证 + 风险评分,不指望单一验证码

    第 2 类最容易被忽略:多数团队都会做 IP 频控,但没有做"单号码频控"。结果是攻击者用 3 万个 IP、每个 IP 只请求一次,同时让某个受害者一分钟内收到 200 条短信——技术上"通过了限流",业务上已经出事(投诉、封号、监管问询)。

    三、四层防御:按性价比排序,别一次全上

    第 1 层:前置人机校验(性价比最划算)

    发码前必须有一步不可自动化的验证:图形验证码、滑块、行为轨迹、点选。

  • 成本:几乎为 0,几行前端代码
  • 收益:挡掉 80% 以上的低成本脚本(它们是批量跑自动化工具的)
  • 注意:图形验证码要服务端校验(前端校验等于没有),并且带一次性 token
  • 第 2 层:多维频率控制(核心)

    单一维度必然被绕过,最少要四维同时生效:

    维度建议阈值(示例)作用
    手机号60 秒 1 次,24 小时 ≤ 10 次挡短信轰炸
    设备指纹24 小时 ≤ 20 次挡一人多号、接码平台
    IP小时 ≤ 30 次,突发峰值限速挡脚本撞库
    账号/会话登录失败 5 次锁 15 分钟挡已注册账号被盗刷

    关键设计:四维是与关系不是或关系——任一维超限就拒绝。只做 IP 维度是最常见的半成品。

    第 3 层:风险识别(决定要不要发)

    频控解决"频",风险识别解决"这个人可不可信":

  • 号段识别:虚拟运营商号段、已知接码平台号段,可提高阈值或直接走二次验证
  • 设备与行为:新设备 + 无历史 + 非常规时段 = 高风险,可要求补一次图形验证
  • 号码本身是否可用:用手机号核验判断号码是否在网,已销户/停机的号码不必发码
  • 这一层的产出应该是一个风险分,而不是二值判断——分数高的走"额外验证",而不是直接拒绝(直接拒绝会误伤真实用户)。

    第 4 层:监控与熔断

    必须有,但排在最后:

  • 发送量突增告警(对比 7 日均值的倍数,不看绝对值)
  • 单号码重复请求 top 榜(这是轰炸的先行信号)
  • 验证通过率异常下降(说明发出去的是给真人的,还是给攻击者的)
  • 熔断开关:一键把验证码通道降级(比如只剩图形验证 + 人工申诉),先止血再排查
  • 四、验证码本身的设计细节

    这些细节不涉及防御架构,但都是真实事故来源:

    □ 6 位数字,5 分钟有效(再长就是给别人时间窗)
    

    □ 一次有效:验证成功后立即失效,不能重复使用 □ 错误次数上限:同一验证码错 3-5 次即作废,防暴力枚举 □ 与手机号绑定校验:A 号码的验证码不能用 B 号码提交 □ 服务端存储 + 单次消费(用 SETNX/条件更新,防并发双花) □ 日志里不明文落库验证码(否则日志系统成了验证码仓库)

    最后一条经常被忽略:验证码写进日志(log.info(f"send {code}"))等于把 5 分钟内的账户控制权暴露给所有能看日志的人。

    五、接短信接口时的三个坑

    这三个都写在对接文档里,但都容易在初版实现时踩到。

    坑 1:短信内容必须带【签名】,否则直接被拒

    内容字段里没带【企业签名】的请求不会发出去,返回错误码(我们这个通道是 1009)。联调时"提示发送成功但用户收不到"的情况,先确认内容是 【签名】您的验证码是 123456,5 分钟内有效。 这个结构。

    坑 2:签名算式与同类接口不一致——不含时间戳

    sms 通道:sign = md5(mall_id + phone + code + appkey)    ★ 没有 tm
    

    核验类通道:sign = md5(mall_id + realname + idcard + tm + appkey)

    团队通常会把签名封装成一个通用函数复用。短信通道没有 tm 参数,如果通用函数固定拼接时间戳,签名必然对不上,而且报错信息往往只给"签名错误",很容易被误判成密钥问题查半天。

    建议:签名函数按接口分别实现,或明确传入参与签名的字段列表,不要写死。

    坑 3:自动重发会与通道自带重发叠加,造成重复扣费

    部分通道(含我们的)对 5 分钟内未送达的短信会自动重发一次,仍失败自动退费。

    这意味着:如果你在业务层再写一个"30 秒没收到回执就重发"的逻辑,就可能出现同一条短信被发两次——用户收到两条验证码、你被扣两条费用、回执维度还难以对账。

    正确做法:业务层不自动重发,走"用户手动点击重发 + 手机号频控";如果一定要做自动化重发,先确认通道的重发策略并与回执状态对齐。

    六、被刷了之后怎么止血

    顺序很重要,别一上来就关接口:

    1. 开熔断:全站验证码切到"图形验证 + 人工复核"(业务降级但不停服)
    
  • 定位维度:拉最近 1 小时发送明细,按 IP / 号段 / 设备分别聚合,
  • 找出集中维度(通常 1-2 个维度占 90% 以上)

  • 拉黑:对该维度加黑名单 + 收紧阈值
  • 通知:涉及向真实用户乱发的,按平台规则报备(这一步别省)
  • 复盘:把这次的维度写进告警规则,防止换个维度再来一次
  • 第 4 步是很多人不做、但后果最重的:通道被投诉到一定程度会被运营商限流甚至封停,影响的是后续所有正常业务,成本远高于那一晚的账单。

    七、上线检查单

    □ 发码前有人机校验,且服务端校验 + 一次性 token
    

    □ 频控四维齐全:手机号 / 设备 / IP / 账号,且为"与"关系 □ 单号码频控已配置(防短信轰炸) □ 验证码:6 位、5 分钟、一次性、错误 3-5 次作废 □ 验证码不明文进日志,不落库明文 □ 签名按接口实现(短信通道不含 tm),不套用统一函数 □ 业务层不叠加自动重发,重发走用户手动 + 频控 □ 发送量突增告警 + 一键熔断开关 □ 密钥分环境隔离,日志脱敏 □ 有报备流程预案(被投诉时怎么处理)

    相关阅读

  • 短信验证码接口:三网合一通道、变量短信、实时状态回执
  • 短信签名模板报备流程:签名规则与驳回原因(本篇讲防刷,报备细节看这篇)
  • 消息通知接口接入指南:签名规则、模板报备与发送频率控制的接入视角
  • API 签名机制一篇讲透:md5 签名的安全的原理与字段约束
  • 批量实名核验怎么并发:配额、限流与断点续跑:服务端限流与并发配额的工程做法
  • 短信通道的计费按条约定、签名与模板需报备,具体与商务确认;新用户有免费试用额度可用于联调。
    #短信验证码#验证码防刷#短信轰炸#频率控制#接口安全

    看完想立刻接入?

    100 次免费调用,1 个工作日开通

    限时新用户 100 次免费

    1 个工作日开通 · 7×24 技术支持