scadastrangelove/zhet-blackhole
GitHub: scadastrangelove/zhet-blackhole
一个提供真值对照的 Python ASGI 模拟服务器,用于黑箱扫描器的测试、教育评估和可复现基准测试。
Stars: 2 | Forks: 0
# 带有 truth 的 Blackhole 模拟服务器

Blackhole 是一个 Python ASGI mock server,用于**黑箱扫描器测试、教育和可复现基准测试**。它通过重放配置文件和显式的有状态小流程来提供看起来有漏洞的行为,同时暴露一个 **truth/scoring API**,以便将扫描器的发现与预期案例进行对比。
换句话说:扫描器可能会产生幻觉、过拟合、恐慌或吹嘘。Blackhole 会保留所有收据。
而且每个白帽都应该记住:所有请求最终都会落入黑洞。

## 总体理念
大多数扫描器演示过于干净、浅显或戏剧化。真实的目标充满噪音。对照组很重要。误报很重要。二阶流程很重要。“看起来有漏洞”不等于“真的有漏洞”。
Blackhole 的存在就是为了明确这种区别。
它提供给你:
- 用于黑箱测试的**可重放的看似有漏洞的行为**
- **safe/control 分支**,以便你可以衡量误报抑制,而不仅仅是嘈杂的检测
- 用于不适合单个请求的情况的**有状态多步骤流程**
- **机器可读的基本真值**,这样结果可以被评分,而不是仅凭感觉争论
- 一个紧凑的教育实验室,用于理解扫描器逻辑在现实但受控条件下的表现
这不是一个生产环境的蜜罐。它不是为猎奇游客准备的漏洞动物园。它是为那些想要测试扫描器、改进检测逻辑、比较构建版本以及教导他人信号和噪音究竟是什么样子的人准备的 **ground-truth harness**。
## 主要用例
### 1. 扫描器测试
将 Blackhole 作为确定性目标用于:
- 回归测试
- FP/FN 分析
- 匹配器调优
- 爬虫和 payload 评估
- 扫描器版本之间的背靠背比较
- 与其他工具或北极星基准的比较
### 2. 教育
使用 Blackhole 来演示:
- 为什么基于 Banner 的检测是脆弱的
- 为什么多步骤工作流很重要
- 为什么“存在错误”不足以证明可利用性
- 为什么 safe/control 分支对于现实评估是必要的
- 扫描器输出应该如何与真值比较,而不是与神话比较
### 3. 基准测试的 Ground-truth 源
Blackhole 暴露一个 **truth manifest** 和评分端点,因此它可以作为基准测试底座用于:
- 内部 QA
- CI 回归包
- 工程验收测试
- 研究实验
- 你想要可重复性而非民间传说的演示环境
## 包含内容
### 核心引擎
- 带有 matcher + response + truth 字段的重放 DSL
- 用于匹配 method/path/query/header/cookie/body/JSON 字段的请求匹配器
- 带有 Jinja2 模板的动态响应渲染器
- 用于多步骤流程的小型场景状态机
- truth/scoring 端点
- 用于健康检查、配置文件、日志、状态、包加载、重置、评分的 admin API
- 从规范化公共语料库到运行时包的编译器
### 入门和基线内容
- 包含反射型 XSS、开放重定向、宽松 CORS、SQL 错误泄露、GraphQL introspection、路径遍历、秘密暴露、存储型 XSS 以及显式二阶 webhook/import/OAuth 流程的入门包
- 大型基线/遗留扫描器包
- 许多案例的 safe/control 变体,以便基准测试可以同时衡量检测和克制
### 基线 / 遗留覆盖
- HTTP auth challenges: Basic, Digest, NTLM, Negotiate
- 表单登录弱口令 vs 锁定控制
- 密码恢复枚举 vs 通用响应控制
- 通过 OPTIONS 进行风险 HTTP 方法检测
- TRACE 启用 vs 禁用控制
- 可写 PUT vs 拒绝控制
- WebDAV 可写 vs 只读控制
- 备份文件、交换文件、归档暴露
- web.config, phpinfo, .git/HEAD, .svn/entries
- Tomcat manager 和 server-status 样式的管理发现
- crossdomain.xml 和 clientaccesspolicy.xml
- 敏感的 robots.txt 条目和目录列表索引
### 较新覆盖
- 带有 safe controls 的 DOM XSS 和客户端 HTML 注入实验室
- 授权/对象状态包:顺序 ID、不透明共享令牌、批量导出 authz、二阶审批流程
- 可预测令牌 / 暴力破解包:重置令牌、邀请令牌、session id、带 safe controls 的 OTP 验证/重发
- OIDC 配套包:发现文档、JWKS、request_uri 流程、WebFinger 枚举
## 包含包计数
- 入门配置文件:54
- 编译的公共语料库配置文件:171
- 组合配置文件:225
## 快速开始
```
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python -m uvicorn blackhole.app.main:app --reload --port 8010
```
偏向生产的示例:
```
python -m uvicorn blackhole.app.main:app --host 0.0.0.0 --port 8010 --workers 2 --log-level info --no-server-header
```
然后访问:
- `GET /__blackhole/health`
- `GET /__blackhole/profiles`
- `GET /__blackhole/truth-manifest.json`
- `GET /login`
- `GET /webdav/`
- `GET /auth/basic`
- `GET /crossdomain.xml`
- `TRACE /trace`
- `OPTIONS /api/methods`
## 命令行参数
Blackhole 通常通过 `uvicorn` 启动,因此有效的运行时开关是 `uvicorn` 命令行选项。以下是完整的附加选项列表,保留作为当前 README 修订版的权威启动接口。
### 用法
```
python -m uvicorn [OPTIONS] APP
```
### 完整选项列表
```
Usage: python -m uvicorn [OPTIONS] APP
Options:
--host TEXT Bind socket to this host. [default:
127.0.0.1]
--port INTEGER Bind socket to this port. If 0, an available
port will be picked. [default: 8000]
--uds TEXT Bind to a UNIX domain socket.
--fd INTEGER Bind to socket from this file descriptor.
--reload Enable auto-reload.
--reload-dir PATH Set reload directories explicitly, instead
of using the current working directory.
--reload-include TEXT Set glob patterns to include while watching
for files. Includes '*.py' by default; these
defaults can be overridden with `--reload-
exclude`. This option has no effect unless
watchfiles is installed.
--reload-exclude TEXT Set glob patterns to exclude while watching
for files. Includes '.*, .py[cod], .sw.*,
~*' by default; these defaults can be
overridden with `--reload-include`. This
option has no effect unless watchfiles is
installed.
--reload-delay FLOAT Delay between previous and next check if
application needs to be. Defaults to 0.25s.
[default: 0.25]
--workers INTEGER Number of worker processes. Defaults to the
$WEB_CONCURRENCY environment variable if
available, or 1. Not valid with --reload.
--loop [auto|asyncio|uvloop] Event loop factory implementation.
[default: auto]
--http [auto|h11|httptools] HTTP protocol implementation. [default:
auto]
--ws [auto|websockets|websockets-sansio|wsproto]
WebSocket protocol implementation.
[default: auto]
--ws-max-size INTEGER WebSocket max size message in bytes
[default: 16777216]
--ws-max-queue INTEGER The maximum length of the WebSocket message
queue. [default: 32]
--ws-ping-interval FLOAT WebSocket ping interval in seconds.
[default: 20.0]
--ws-ping-timeout FLOAT WebSocket ping timeout in seconds.
[default: 20.0]
--ws-per-message-deflate BOOLEAN
WebSocket per-message-deflate compression
[default: True]
--lifespan [auto|on|off] Lifespan implementation. [default: auto]
--interface [auto|asgi3|asgi2|wsgi]
Select ASGI3, ASGI2, or WSGI as the
application interface. [default: auto]
--env-file PATH Environment configuration file.
--log-config PATH Logging configuration file. Supported
formats: .ini, .json, .yaml.
--log-level [critical|error|warning|info|debug|trace]
Log level. [default: info]
--access-log / --no-access-log Enable/Disable access log.
--use-colors / --no-use-colors Enable/Disable colorized logging.
--proxy-headers / --no-proxy-headers
Enable/Disable X-Forwarded-Proto,
X-Forwarded-For to populate url scheme and
remote address info.
--server-header / --no-server-header
Enable/Disable default Server header.
--date-header / --no-date-header
Enable/Disable default Date header.
--forwarded-allow-ips TEXT Comma separated list of IP Addresses, IP
Networks, or literals (e.g. UNIX Socket
path) to trust with proxy headers. Defaults
to the $FORWARDED_ALLOW_IPS environment
variable if available, or '127.0.0.1'. The
literal '*' means trust everything.
--root-path TEXT Set the ASGI 'root_path' for applications
submounted below a given URL path.
--limit-concurrency INTEGER Maximum number of concurrent connections or
tasks to allow, before issuing HTTP 503
responses.
--backlog INTEGER Maximum number of connections to hold in
backlog
--limit-max-requests INTEGER Maximum number of requests to service before
terminating the process.
--limit-max-requests-jitter INTEGER
Maximum jitter to add to limit_max_requests.
Staggers worker restarts to avoid all
workers restarting simultaneously.
[default: 0]
--timeout-keep-alive INTEGER Close Keep-Alive connections if no new data
is received within this timeout (in
seconds). [default: 5]
--timeout-graceful-shutdown INTEGER
Maximum number of seconds to wait for
graceful shutdown.
--timeout-worker-healthcheck INTEGER
Maximum number of seconds to wait for a
worker to respond to a healthcheck.
[default: 5]
--ssl-keyfile TEXT SSL key file
--ssl-certfile TEXT SSL certificate file
--ssl-keyfile-password TEXT SSL keyfile password
--ssl-version INTEGER SSL version to use (see stdlib ssl module's)
[default: 17]
--ssl-cert-reqs INTEGER Whether client certificate is required (see
stdlib ssl module's) [default: 0]
--ssl-ca-certs TEXT CA certificates file
--ssl-ciphers TEXT Ciphers to use (see stdlib ssl module's)
[default: TLSv1]
--header TEXT Specify custom default HTTP response headers
as a Name:Value pair
--version Display the uvicorn version and exit.
--app-dir TEXT Look for APP in the specified directory, by
adding this to the PYTHONPATH. Defaults to
the current working directory. [default:
""]
--h11-max-incomplete-event-size INTEGER
For h11, the maximum number of bytes to
buffer of an incomplete event.
--factory Treat APP as an application factory, i.e. a
() -> callable.
--help Show this message and exit.
```
### 实用启动示例
开发:
```
python -m uvicorn blackhole.app.main:app --reload --port 8010
```
监听所有接口:
```
python -m uvicorn blackhole.app.main:app --host 0.0.0.0 --port 8010
```
两个 worker,更少的头信息:
```
python -m uvicorn blackhole.app.main:app --workers 2 --no-server-header --log-level info
```
uvicorn 内部 TLS 终止:
```
python -m uvicorn blackhole.app.main:app --host 0.0.0.0 --port 8443 --ssl-certfile ./certs/server.crt --ssl-keyfile ./certs/server.key
```
## 如何使用
### 作为测试目标
1. 在本地或 CI 中启动 Blackhole。
2. 针对它运行你的扫描器。
3. 收集发现。
4. 将发现与 truth manifest 或 scoring API 进行比较。
5. 调查:
- 哪些被正确发现
- 哪些被遗漏
- 哪些不应该触发
- 哪些流程需要状态、排序或更好的匹配器逻辑
### 作为教育实验室
使用单独的包和端点向学生或工程师展示:
- 扫描器看到了什么
- 服务器实际上知道什么
- 朴素的签名在哪里失败
- 对照组与易受攻击的案例有何不同
- 为什么 ground truth 是房间里唯一成熟的人
### 作为基准测试底座
当你需要一个**可重复的真值源**时,Blackhole 特别有用:
- CI 中的回归门控
- 夜间扫描器比较
- 调整新的检测系列
- 验证误报的减少
- 评估爬虫、payload 或后处理更改
## Truth 模型
Blackhole 不仅仅发出行为。它还告诉你该行为意味着什么。
该项目通过 truth manifest 和相关的 scoring/admin 端点暴露**机器可读的 truth hints**。这允许你将目标视为 **ground-truth source**,而不仅仅是一个带有可疑页面的戏剧性 Web 应用程序。
这很重要,因为许多基准测试目标只回答一个问题:*演示 payload 能否触发有趣的事情?*
Blackhole 试图回答更有用的问题:
- 该案例是否真的存在?
- 是否仅在特定条件下存在?
- 是否有 safe/control 分支?
- 该问题是一阶还是二阶的?
- 扫描器检测到的是信号,还是仅仅对噪音做出了反应?
## 备注
- 许多基线案例都包含 safe/control 分支,以便基准测试可以衡量误报抑制以及检测。
- 自定义内置流程通过 truth manifest 和发现页暴露机器可读的 truth hints。
- 该项目对**测试、教育和 ground-truth 驱动的评估**很有用。
- 如果你的扫描器看到了幽灵,Blackhole 不会争辩。它会给它们打分。
## 哲学
安全测试充满了建立在不可靠证据上的英勇确定性。
扫描器看到一个堆栈跟踪就宣布胜利。
基准测试展示一个玩具登录表单就自称现实主义。
仪表盘把所有东西涂成红色,并希望没人问“和什么相比?”
Blackhole 就是为了那个令人不安的后续问题而构建的。
它是一个小的人造世界,外表可能具有欺骗性,控制看起来可能很诱人,但如果你足够自律去索取,真相仍然是可以获得的。
因为这就是黑箱测试的整个笑话:你凝视黑暗,向虚空发送请求,并希望意义能回来。有时会。有时那只是你自己的倒影,被引力扭曲了。
## 作者
**Sergey Gordeycik**
serg.gordey@gmail.com
https://scadastrangelove.blogspot.com/
## 版权
**(c) Sergey Gordeycik**
## 许可证
本项目采用故意的非商业许可模式。
### 代码
除非另有说明,**源代码**在 **PolyForm Noncommercial License 1.0.0** 下提供。
这意味着,用通俗的人类语言来说:
- 你可以出于**非商业目的**使用、学习、修改和共享代码
- 你可以将其用于**研究、测试、教育、内部实验工作、和基准测试**
- 未经作者单独许可,你**不得**将其用作商业产品、付费服务、面向客户的平台或产生收入的工作流的一部分
### 文档、基准测试包、示例和媒体
除非另有说明,**文档、基准测试描述、示例、README 内容和媒体/艺术品**在 **Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)** 下提供。
这意味着你可以出于**非商业用途**复制、改编和重新分发这些材料,但需注明出处。
### 商业用途
如需商业许可、OEM 式使用、客户交付、托管基准测试服务、产品嵌入或包含 Blackhole 的付费咨询包,请联系:
**Sergey Gordeycik**
serg.gordey@gmail.com
### 为什么选择这种模式
Blackhole 旨在帮助研究、测试、学习和工程真理。它并不是要被光鲜的商业包装悄悄吞噬并作为启示转售。
或者,用更适合这个项目的声音来说:基准测试对于寻求信号的人是免费的;当有人试图将奇点货币化时,账单就会到来。
标签:ASGI, CISA项目, DevSecOps, Hacking, Mock服务器, OPA, Python, Web安全, 上游代理, 加密, 反取证, 回归测试, 安全测试, 安全评估, 密码管理, 开发安全, 攻击性安全, 无后门, 模拟服务, 漏报分析, 漏洞扫描器, 状态流, 真相API, 网络安全, 蓝队分析, 误报分析, 逆向工具, 隐私保护, 靶场, 黑盒测试