SqlStealthRogue:让天底下没有难拖的数据库

· 2026-09-25 00:00 · 4 阅读

原创 侠盗鲁平 2026-09-25 00:00 日本

发出的每一个请求,都是数据提取请求本身

零探测、零协商——发出的每一个请求,都是数据提取请求本身。

0x00 背景

SQL 注入脱库是渗透测试中最常见的收尾动作之一。与漏洞发现不同,脱库的核心不在于"能不能注入",而在于信息已被掌握之后的提取效率——测试报告中早已写明目标是什么数据库、哪张表、哪个字段,剩下的唯一问题是:怎么把数据又快又干净地拿出来。

当前工具生态存在一个被长期忽视的矛盾:

工具

定位

局限

sqlmap

全自动注入利用

即使 -D/-T/-C 全部指定,仍要发大量请求做 DBMS 指纹、版本探测、权限枚举、WAF 检测、技术轮询

nosqlmap

NoSQL 注入利用

线性逐字符探测,以 MongoDB 为主;流量开销大

手工构造

精准可控

效率低,多库多技术组合全靠人肉记忆

核心矛盾:sqlmap 的"全能"建立在自动协商之上——它不知道目标是什么,所以必须先问;而真实测试场景中,目标的信息你早就有了。指纹、版本、权限、技术可行性,这些探查流量在"已知库表列"的前提下全部是浪费——不但拖慢速度,还会在流量侧留下远比脱库本身更扎眼的特征。

SqlStealthRogue 针对的正是这一断层:已知注入点 + 已知查询的前提下,除提取数据本身外,一个多余请求都不发。

0x01 整体架构

SqlStealthRogue 采用"指定即用"的单命令管线(纯 Python 标准库,零依赖):

输入: 注入点(*) + 库(--dbms) + 方式(--technique) + 查询(-q)
  │
  ├─ ① 静态校验   (注入点数量 / 模板合法性 / 库×技术兼容性 —— 0 包拦截)
  ├─ ② 模板解析   (dbms/ 插件注册表自动装配载荷, base 继承链)
  ├─ ③ 提取引擎   (union / error / bool / time / prefix 五算法)
  ├─ ④ 提速层     (位并行 + keep-alive + 分块预取, 全部可关)
  └─ ⑤ 哨兵守卫   (错误配置最小截停, 全程零额外请求)
  │
输出: 数据行 + 流量对账 (行数 | 请求数 | 耗时 | req/s)

没有"环境适配"阶段,没有"可用性检查"阶段——从第一个请求开始就在提取数据。行终止信号全部搭提取请求的便车:报错模式用"子查询为 NULL 则无特征"、布尔模式用"二分收敛到 0 即串结束"、union 一次全量。不存在任何专门用来"看看行不行"的请求。

0x02 五种提取算法

2.1 UNION——整表 1 请求

-U " UNION SELECT NULL,NULL,{Q}#",一次请求带回整个结果集,--regex 逐行提取。SQL 里拼 0x5b5b...0x5d5d([[ ]])标记可让正则与页面结构完全解耦。Milvus 的 expr 注入(改写为全真表达式如 id >= 0 全量拉取)、Redis 的 EVAL return、Elasticsearch 的 painless script_fields 都走这条路——NoSQL 的"union"就是换一种方式让后端直接把数据吐回来。

2.2 报错模式——每 30~500 字符 1 请求

错误回显是信息密度最高的信道。SqlStealthRogue 的分块策略按引擎实测承载上限设定:MySQL extractvalue 上限 31 字符(chunk=30),PG/MSSQL 的 CAST 错误消息实测承载 ≥800 字符(chunk=500)——600 字符的长值从 22 个请求降到 6 个。

快版引擎带自适应窗口分块预取:块位置固定(P, P+N, P+2N...)可投机,窗口 1→2→4→bwidth 并行预取,短读即止。

2.3 布尔盲注——每字符 8 请求,位并行提速 5.35×

串行版是经典 [0,255] 二分。快版换成位并行:char & {mask} > 0 探 8 个 bit——bit 之间互相独立、字符位置之间零依赖,按窗口批量并发。请求数与串行完全相同,关键路径从 len×8 次串行往返塌缩为 len/W 个批次往返(实测 5.35× 提速)。

2.4 时间盲注——刻意串行

无回显差异的注入点用 SLEEP/WAITFOR DELAY/pg_sleep/$where 忙等做 oracle。判真阈值取 --sec 的 3/4——留 1/4 容忍后端硬解析抖动(这是 Oracle 真机上踩出来的:每个探针都是新 SQL 文本,偶发 1-2s 的 parse 尖峰会把 1/2 阈值打成假阳性,污染提取数据)。刻意不并行:并行 SLEEP 会把目标端连接池打满,负载告警先于数据到达。

2.5 prefix——NoSQL $regex 的正确打开方式

MongoDB 表单运算符注入(password[$regex]=^前缀[\x20-\xHH])用字符类二分:对每个字符在可打印 ASCII 上二分字符类上界,~8 请求/字符——nosqlmap 式线性探测在引擎层被压成了对数级。注意一个真机踩坑:字符类下界不可低于 0x20,[\x20-\x1f] 反向区间在 PCRE 中行为未定义,Mongo 里表现为恒真。

0x03 高速的三层叠加

优化

原理

实测效果

位并行

8 bit 独立并发 + 位置投机

5.35×(请求数不变)

HTTP keep-alive

线程本地长连接,省每请求 TCP/TLS 握手

5.6×

分块预取 + 大 chunk

自适应窗口 + 按引擎实测承载

长值 22 → 6 请求

两个值得说的工程细节:

并发模型只有一个旋钮。行级走 --threads 线程池,但所有探测统一收口到 PROBE_POOL(大小 = --bwidth)——无论开多少行并发,实际 HTTP 在途请求数恒等于 bwidth。目标负载可预测,不会因为行并发失控把对方打挂。

keep-alive 对旧协议诚实降级。长连接在 HTTP/1.1 目标上 5.6×,但 HTTP/1.0 或要求断连(Connection: close)的服务端每响应即断,长连接纯付开销——实测反而变慢。所以发送器探测响应版本与断连要求,命中即永久降级回每请求新建连接,零损失。

要最大隐蔽而不是最大速度:--bwidth 1 --threads 1 --delay 0.5,全串行 + 限速。

0x04 过 WAF:插件化 tamper 链

内置 13 个 sqlmap 同名同语义 tamper:space2comment、between(>N → NOT BETWEEN 0 AND N)、randomcase、charencode、halfversionedmorekeywords、xforwardedfor(每请求随机 XFF 头,只改请求头)等,逗号分隔按序组合:

python SqlStealthRogue.py --tamper "randomcase,between,space2comment" ...

自定义插件零门槛:一个 .py 文件一个 tamper() 函数,丢进 --tamper-dir 指定的目录即注册,同名覆盖内置;单参数的 sqlmap 风格脚本直接兼容。

工程上最关键的是统一上链契约 wire_encode:tamper 只负责 SQL 语义变换,输出统一归一化——保留已有 %XX(charencode 成果)和 +(space2plus 语义),只强制编码 URL 结构致命字符(& # ?)、空白与控制字符。这条单一规则来自真机翻车:bit 探针载荷里的 &128 原样上链时,& 把 query 参数直接截断。实测 tamper 链开/关请求数完全相同——绕 WAF 零流量开销。

0x05 错误配置的最小截停

零探测是双刃剑:工具不替你试错,配错参数时它**只回你一句"未取到任何行"**。SqlStealthRogue 把配错的代价钉死在"首行首值"量级:

错误形态

实际发包量

参数静态非法 / 未知 tamper / 库×技术不匹配

0

注入点不通

≤ 2

模板或 true-mark 语法错

8~16

true-mark 恒真 / 正则恒匹配(哨兵守卫中止)

~128(无守卫时 16,384+)

union 模板错

1

哨兵守卫是零额外请求的被动检测:提取值连续 4 个 0xFF(true-mark 同时匹配真假两页的典型特征)或连续 20 行空值(error 正则恒匹配、行终止信号失效)→ 立即中止并给出排查方向。另有 --err-mark:命中后端错误页特征的响应视为无效探针,重试一次仍错则响亮失败——这个功能来自 Oracle 真机上一类静默数据污染:后端错误页被当成"假值"读进 bit,提取出错误数据而无人察觉。

矩阵之外的引擎(如 TiDB / 人大金仓 / 达梦)因二进制获取渠道受阻未纳入验证范围——宁可不说"支持",不假装验证过。

0x07 使用方式

git clone https://github.com/lupingQAQ/SqlStealthRogue.git
cd SqlStealthRogue
# 引擎×技术矩阵 / tamper 清单
python SqlStealthRogue.py --list
python SqlStealthRogue.py --list-tampers
# MySQL 报错脱库(默认), 行迭代自动包裹, 取空即停
python SqlStealthRogue.py -u "http://t/page.php?id=1*" -q "SELECT password FROM users"
# MSSQL / PG 时间盲注 / MongoDB $regex 前缀 / Redis / Milvus ...
python SqlStealthRogue.py --dbms mssql -u "..." -q "SELECT name FROM master..sysdatabases"
python SqlStealthRogue.py --dbms postgres --technique time --sec 5 -u "..." -q "..."
python SqlStealthRogue.py --dbms mongodb --technique prefix --true-mark "登录成功" \
  -u "http://t/login" --data "password[$regex]=*" -q password

新增一个数据库 = 在 dbms/ 加一个几十行的 PROFILE 文件,零注册代码;兼容库走 base 继承——pgvector 整个文件只有一行 base: 'postgres'(它本体就是 PostgreSQL)。

0x08 与现有工具对比

维度

sqlmap

nosqlmap

SqlStealthRogue

协商/探测流量

大量(指纹/版本/权限/WAF/技术轮询)

中(线性探测)

0

(逐请求对账验证)

引擎覆盖

30+ 数据库(含 NoSQL)

以 MongoDB 为主

12 引擎真机验证(SQL/NoSQL/国产/向量)

需预知目标信息

否(自动识别)

部分

是

(已知注入点+库表列)

提取速度

—

慢(线性)

位并行 5.35× + keep-alive 5.6×

过 WAF

tamper 库

无

tamper 链 + 自定义目录(零额外流量)

错误配置行为

探测阶段失败

探测阶段失败

最小截停(0 ~ 128 包,哨兵守卫)

工程形态

大型工程(多文件)

Python + 依赖

纯标准库零依赖,单文件入口

流量侧特征

探查流量远比提取扎眼

高请求量

只有提取流量,且总量 = 理论最小值 ± 有界溢出

一句话定位:sqlmap 是不知道目标是什么时的瑞士军刀;SqlStealthRogue 是你知道目标是什么时的手术刀。

0x09 局限与声明

  • 位并行以全 0 字节判串结束:二进制数据(BLOB)请用 error/union

  • 盲注逐字节提取:多字节字符(中文)按单字节取出会乱码;error/union 整段传输不受影响

  • time 模式刻意串行,追求的是不打挂目标而不是速度

  • 零探测的代价:工具不做任何自我诊断,注入点/模板配错时只提示"未取到任何行"

  • 矩阵之外的引擎(TiDB/Kingbase/DM 等)未纳入验证范围,不代表不可用,只代表没验过

  • 需要"自动识别目标"的场景请用 sqlmap——两种工具是互补不是替代

仅用于合法安全研究、教育和授权渗透测试。未经授权对他人系统使用属违法行为。

参考

  • sqlmap — tamper 语义参照

  • nosqlmap — NoSQL 注入探测对比参照


GitHub: https://github.com/lupingQAQ/SqlStealthRogue

WeChat: IndexSec

跳转微信打开