ARTICLE · 1000844
“一个码,三种用法”:我在某App上靠复用验证码搞定了任意账户接管
2026年了,我本来以为“验证码复用”这种低级错误早该绝迹。结果上周测一个刚上线的金融App,它用实际行动证明我想多了。
这个App的注册、登录、重置密码三个环节,都会给同一个手机号发短信验证码。我做了个实验:用注册接口触发验证码,然后用这同一个码去登录接口——成功。再用它去重置密码接口——又成功。
一个码,三种用法,凭一个手机号就能把别人账户掀翻。
别小看这个漏洞。它不是“验证码没设有效期”那种老生常谈,而是“验证码语义没隔离”——系统只认“这个码对不对”,不认“这个码是干嘛来的”。今天我把这个漏洞的完整思路、实战利用链和防御方式全部拆开。
一、漏洞本质:验证码应该“绑定场景”,不只是“绑定手机号”
一个合格的短信验证码系统,应该是这样的:
注册时生成的验证码,只能用于注册。
登录时生成的验证码,只能用于登录。
重置密码时生成的验证码,只能用于重置密码。
而且每个验证码都应绑定手机号、绑定当前会话、有效期短、用完即焚。
但很多系统的实现是:
验证码存在Redis里,key是
sms:code:{phone}。任何需要验证码的接口,都从同一个key里取。
只要传进来的验证码和Redis里的值一致,就放行。
这就有个大问题:验证码本身不记录“生成目的”。如果你在注册页拿到一个码,然后去登录接口输入,系统看这个码和手机号对得上,就让你登录了。至于这个码“本来”该做什么,它根本不关心。
这就是“验证码复用”漏洞的核心——缺少场景绑定。攻击者可以用最宽松的验证码入口(比如注册)获取验证码,然后把它用到最危险的操作上(比如重置密码),完成任意账户接管。
二、三个实战场景:一个码怎么玩出花
为了让你看得更清楚,我把它拆成三个具体的攻击链路。以下全部来自脱敏的授权测试。
场景一:注册码直接登录
某打车App,登录和注册用同一个短信验证码接口POST /api/sms/send。请求参数都是{"phone":"138xxxx"}。
我输入别人的手机号,触发验证码。对方手机收到一条“您的注册验证码是1234”。我没法看到短信内容?没关系——我先测了自己手机号的验证码,发现它不设频率限制、不绑设备。于是我写了个脚本,连续触发验证码,直到把4位数字爆破出来。
拿到验证码后,我在登录接口输入别人的手机号加这个验证码。登录成功。账户里的行程、支付方式、常去地点全暴露。
场景二:登录码重置密码
某社交App,登录验证码和重置密码验证码共用同一个Redis key。我用登录接口触发验证码,对方手机收到“您的登录验证码是5678”。这个码在重置密码接口依然有效。
我把验证码填进去,设置一个新密码。对方号主直接失去账户控制权。
场景三:注册码修改绑定手机号
某网赚平台,注册验证码也能用来修改绑定手机号。攻击者用自己的手机号触发验证码,然后在“修改绑定手机号”接口输入这个码,把对方账户的绑定手机号改成自己的。此后所有验证码都发到攻击者手上,账户被永久接管。
看到没?一个验证码复用漏洞,可以组合成任意账户接管。这就是它最危险的地方。
三、怎么系统性挖掘这类漏洞?
第一步:枚举所有涉及验证码的业务接口。 注册、登录、找回密码、修改手机号、绑定第三方账号、修改交易密码……把这些接口全列出来。
第二步:抓包分析验证码的存储方式。 触发一个验证码,看请求参数里有没有scene、type、purpose之类的字段来区分场景。如果没有,说明验证码可能不绑定场景,复用漏洞的可能性大增。
第三步:做交叉验证。 在A场景触发的验证码,拿到B场景去用。如果B场景也接受,那就是验证码复用漏洞。
第四步:测试“万能验证码”。 有些系统在开发时为了方便,写死了123456或000000作为万能码,上线后忘了删。测试时优先试这几个码。
第五步:判断是否为高危。 如果复用的验证码能导致任意账户接管(比如重置密码),直接定严重;如果只能导致信息泄露或中等危害,定高危或中危。按实际影响写报告。
四、防御方案
验证码绑定场景标识。 Redis key改成
sms:code:{scene}:{phone},同时在业务层验证场景。注册码不能用于登录,登录码不能用于重置密码。验证码绑定操作目标。 如果验证码用于修改手机号,还要绑定新手机号和当前用户ID,防止横向越权。
验证码一次性使用。 验证成功后立即删除Redis里的记录。如果再复用,直接报错。
设置短有效期。 一般5分钟,最多不超过15分钟。
失败次数限制。 一个手机号验证码最多尝试3-5次,超过立即失效。
异常行为监控。 对同一手机号在短时间内发送大量验证码、或在多个场景间交叉尝试的行为进行告警。
五、写在最后
验证码复用是业务逻辑漏洞里最被低估的一类。它没有SQL注入那么花哨,没有越权那么直白,但它可以在极短时间内完成从“拿一个码”到“接管道账户”的攻击链。
2026年,Web应用的功能越来越复杂,验证码的使用场景也越来越多。但很多团队在新增一个验证码场景时,只是简单复用老接口,从没想过“这个码该不该绑定场景”。安全不做重新设计,漏洞就会像野草一样从缝隙里长出来。
下次你测App或者Web系统,多留意验证码。同一个码,在注册页拿了,去登录页试试,再去重置密码页试试。说不定一条完整的账户接管链,就在这三个页面之间等着你。
严正声明本文所述技术仅用于合法授权的安全测试。所有案例均已脱敏处理。利用验证码复用漏洞进行未授权操作属于违法行为,与作者无关。请在SRC平台授权范围内进行测试,遵守法律法规。