短信验证码发送场景的安全设计实践

181 阅读4分钟

短信验证码(SMS OTP)广泛应用于登录、注册、交易确认、账号绑定等关键业务流程。
但在安全设计上,“能发短信”并不等于“短信发送是可控的”。

如果缺乏系统性的安全约束,短信接口很容易被滥用为:

  • 短信轰炸工具
  • 用户骚扰与社工入口
  • 绕过风控或消耗资源的攻击面

本文结合实际业务与安全实践,从 发送频控、发送对象数量控制、短信内容可信性 三个关键方向,总结短信验证码场景中必须具备的安全设计能力。


一、发送频控:以“主体维度”做强限制

1. 风险背景

短信接口的第一道防线是频控,但如果频控仅停留在 手机号维度,攻击者只需不断切换号码即可轻易绕过限制。

因此,频控必须围绕“主体”而非“单一参数”设计。


2. 频控维度设计建议

推荐在短信发送接口中,至少引入以下维度进行限制:

  • 设备维度
    • deviceId、设备指纹、设备画像,以及任何能够唯一标识该设备的字段,都能用于频控
    • 用于识别同一物理或逻辑设备的高频行为
  • IP / 网络维度
    • 源 IP、IP 段、ASN
    • 防止脚本或代理池批量触发
  • 账号维度
    • 账号 ID、登录态、业务身份、以及任何能够唯一标识该用户的字段,都能用于频控
    • 限制单账号异常触发短信能力
  • 手机号维度
    • 单手机号在分钟 / 小时 / 天级别的发送上限

3. 实践建议

  • 采用多维度叠加限制(想象成把这些判断参数都放进一个篮子,只要其中一个参数命中,就算命中防御),而非单点判断
  • 形成 短期 / 中期 / 长期 的梯度限制策略
  • 在异常高频触发时,引入:
    • 图形验证码
    • 行为验证码
    • 二次校验
  • 记录频控命中日志,用于后续安全分析与策略调优

设计目标:

让单一主体无法通过切换手机号、IP 或设备来持续突破短信发送限制。


二、发送对象数量控制:防止“群发式”滥用

1. 场景问题

短信验证码的本质是 “向单一用户发送的安全凭证”
但在实际业务中,常会出现以下扩展场景:

  • 卡片分享
  • 邀请好友
  • 好友协助 / 转赠

如果对发送对象数量缺乏限制,这类接口极易被滥用为 短信骚扰或群发工具


2. 典型风险点

  • 前端可控发送对象数量
  • 单次请求携带大量手机号
  • “分享 / 邀请”场景被滥用为群发入口

即使接口逻辑正确,也可能引发:

  • 用户投诉
  • 运营风险
  • 合规与监管风险

3. 安全设计建议

  • 评估业务合理对象数量
    • 例如:卡片分享默认 1 人,最多 3 人
  • 设置单次与周期性上限
    • 防止通过多次操作绕过限制
  • 分场景差异化限制
    • 分享、邀请、绑定等场景上限应不同
  • 非核心场景严禁大规模发送
    • 超过阈值直接拦截,而非降级放行

设计目标:

明确“合理数量”,让短信发送始终保持“单用户验证”的安全属性。


三、短信内容不可前端可控:防止信任边界错位

1. 风险说明

如果短信内容由前端直接传参或拼装,将引入严重的信任边界问题:

  • 攻击者可构造钓鱼、误导性文本
  • 服务端被动“信任前端”,导致语义失控
  • 绕过业务规则发送非预期短信内容

前端输入天然不可信,短信内容尤其如此。


2. 核心设计原则

  • 短信内容必须由服务端模板生成
  • 前端仅传递必要的业务标识信息
    • 如:场景类型、操作标识
  • 服务端对前端可控参数进行严格合法性校验

3. 实践建议

  • 使用 模板 ID + 参数占位 的生成方式
  • 对可控参数进行:
    • 白名单校验
    • 长度限制
    • 格式与字符集校验
  • 严禁前端直接传入完整短信正文或可拼接内容

设计目标:

服务端完全掌控短信内容与语义,前端仅负责触发业务场景。


四、总结

短信验证码的安全设计,并不是“加一个验证码接口”就结束,而是需要在以下三条线上建立完整防护:

  • 频控:多维度限制,防止切换主体绕过
  • 对象数量:限制发送范围,避免被滥用为群发
  • 内容控制:模板化生成,前端不可直接控制内容

只有把这些基础能力设计清楚,
短信验证码才能真正成为 安全体系的一环,而不是攻击入口。 以下是一些典型场景的安全防控措施总结

image.png


后续可结合风险模型与用户行为分析,对短信发送能力进行动态调节与分级控制。