短信、OTP 与付费接口
在滥用请求变成账单之前拦住它们。
本页内容
攻击者可以用脚本批量调用公开的发送接口,而应用看起来一切正常。损失体现在账单上,往往流量停了以后才发现。
让 AI agent 审查付费调用
Prompt
审查 [Jira 编号、PR 链接或 diff] 是怎么调用付费服务商的。
如果是 Jira ticket,通过已连接的 Jira MCP 或已认证的 acli 读取描述、验收标准和评论;无法访问时,让我粘贴详情。
把每个付费调用从请求检查一路追到服务商调用和费用记账。用 mock 或测试服务,对照本页的要求检查限流、消费上限、kill switch 和告警。
逐条报告可以绕过的地方,附上证据。
说明本页列出的测试哪些已在项目测试套件里。能自动化的补上,其余的列出来。
不要发送真实消息,也不要产生费用。发送前检查请求
- 公开的 OTP 发送之前,在服务端校验人机验证。只在客户端检查,可以被绕过。
-
每个维度都要限流。按手机号、IP、设备和账号分别限流,另加每分钟和每天的全局上限。
注意在调用服务商之前检查限流,重发也一样。
-
只发往产品服务的国家。其他国家的请求在到达服务商之前就拒绝。
注意国家从解析后的手机号里取,不要用客户端可控的国家选择器。
- 先规范化手机号,再做限流。计数器在并发的 worker 之间必须一致。限流检查不了时,就不发送。
- 限流要在应用里做。负载均衡或 CDN 的限流有帮助,但只有应用知道手机号、账号和设备。
- 客户端 IP 只从可信代理设置的 header 里取,不要用客户端能伪造的 header。否则负载均衡后面的所有用户共用一个 IP,按 IP 的限流要么拦住所有人,要么谁都拦不住。
- 重发间隔在服务端控制:例如 30 秒、60 秒、5 分钟,之后暂停一小时。实际限额按预期流量来定,并记录在仓库里。
- 不管账号是否存在,对外返回相同的响应;具体的拒绝原因记在内部指标里。
限制花费并监控验证率
-
付费调用之前检查硬性消费上限,超了就不发。所有 worker 共用一份预算,用原子操作扣减。服务商提供的消费上限、告警和反欺诈功能也要开启;光有告警拦不住花费。
注意服务商的控制是应用限额的补充;确认哪些设置真的会拦截请求。
- kill switch 不需要部署就能停止所有发送。
- 验证率下降时告警:验证率是同一时间窗口内验证成功的验证码数除以发出的验证码数。下降时要排查滥用、投递失败和验证流程故障。
- 超时的发送仍可能被计费。在服务商确认结果之前,保留它占用的预算;超时只说明结果未知。
失败案例 · 示意
安静的周六
周末,发往服务范围之外国家的短信涨到平时的三倍,几乎没有验证码完成验证。目的国家白名单本可以拦下这些发送;即使攻击者把请求分散到大量号码上,消费上限也能控制住账单。
其他付费 API 也要设费用限制
- 邮件、语音、地图、KYC 和模型调用,都需要按业务流程做调用方鉴权或防滥用检查,并设置按调用方的配额、全局费用上限和 kill switch。
- 手机号验证还要加上国家和验证率控制。其他 API 则对照成功的业务结果来看费用。
- 服务商的凭据只放在服务端;调用服务商时按后台任务与外部调用的做法来:显式超时,只在安全时重试,统一限流。
测试这些限制
- 同一号码一分钟内发起 100 次请求,实际发送数不超过限额。
- 发往白名单以外国家的请求被拒绝,且没有调用服务商。
- 在 staging 打开 kill switch,一分钟内停止发送。
- 模拟一次验证率下降,验证率告警会触发。
- 用并发请求把消费预算用完:没有任何 worker 超出上限多发。
- 让限流存储不可用:不会调用服务商。
- 分别带一个无效的人机验证 token、不带 token、绕过前端直接请求后端:三种情况都走不到付费发送。