maximeroucher/heimdall
GitHub: maximeroucher/heimdall
一个面向 FastAPI 应用的自动化 OWASP Top-10 渗透测试库,通过自动发现路由与认证机制实现近乎零配置的安全评估。
Stars: 0 | Forks: 0
# Heimdall
**一个用于 FastAPI 应用的自动发现型 OWASP Top-10 渗透测试库。**
它源于对某个应用的手写渗透测试,随后被泛化,使得相同的方法论能够以近乎零的每个应用配置,针对**任何** FastAPI 服务运行。
## 为什么它是通用的
大多数渗透测试脚本会硬编码路径(`/core/auth/login`)、凭据以及受害者的数据模型。Heimdall 不会。它会**自动发现**它们:
| 关注点 | Heimdall 如何获取信息 |
|---|---|
| 每个路由、方法、必要的认证、参数、body schema | `GET /openapi.json`(每个 FastAPI 应用都会提供) |
| 登录格式(JSON 还是 OAuth2 form 还是 `simple_token`) | 对 OpenAPI 操作的启发式评分 |
| 注册 / “当前用户” endpoint | 同上 |
| 认证传输方式 — bearer token **或** cookie-session | `securitySchemes` + 实时的登录响应(302/204 + `Set-Cookie` → cookie jar;`Authorization` scheme → token) |
| JWT 算法与 claim 结构 | 解码通过登录流程生成的真实 token |
| 候选签名密钥、依赖堆栈 | 对源码树进行可选的白盒扫描(`--source`) |
随后,各个模块会基于这个发现的映射来运作 —— 因此只需编写一次检查(“受保护的路由必须拒绝匿名调用者”),就能针对任何 FastAPI 应用运行,无需任何改动。认证格式检测意味着 CSRF 和 session 模块会在使用 cookie-session 的应用上激活,而在 token API 上保持静默,且无需进行每个应用的单独配置。
## 安装
```
uv pip install -e '.[full]' # full = JWT forging + pip-audit + TOML on 3.10
# 或最小化安装:uv pip install -e .
```
## 使用
### CLI
```
# 黑盒,仅 discovery(无 attack)——安全的第一步检查:
heimdall --url http://127.0.0.1:8000 --discover-only
# 全面评估,白盒(source tree 启用 JWT-secret + component 检查):
heimdall --url http://127.0.0.1:8000 \
--source /path/to/YourApp \
--cred admin:admin:admin@you.io:hunter2 \
--cred member:user:member@you.io:pw
# 或者从 config 文件:
heimdall --config examples/example.toml
# Non-destructive pass,或限定在特定 module:
heimdall --url http://127.0.0.1:8000 --safe
heimdall --url http://127.0.0.1:8000 --only a01,a02
heimdall --url http://127.0.0.1:8000 --skip race,cmdi,xxe
heimdall --list-modules
```
#### 完整 flag 参考
| Flag | 用途 |
|---|---|
| `--url URL` | 目标基础 URL(必填,除非由 `--config` 提供)。 |
| `--source PATH` | 目标源码树 — 启用白盒检查(JWT 密钥恢复、`a06` 组件、`sast`)。 |
| `--name NAME` | 用于报告的友好应用名称。 |
| `--config FILE` | TOML/JSON 目标配置(CLI flag 会覆盖其中的字段)。 |
| `--cred label:role:identifier:password` | 登录凭据;可重复使用。`role` 格式不限(`admin`、`user` 等),并驱动 BFLA/BOLA 配对。 |
| `--launch CMD` / `--launch-cwd DIR` | 首先使用 shell 命令启动目标(及其工作目录),随后将其销毁。目标自身的 stdout/stderr 将被捕获到临时日志中,如果启动失败,将打印其末尾内容。 |
| `--launch-timeout SECONDS` | 等待 `--launch` 目标响应的时长(默认 180 秒)。对于在首次启动时运行迁移/种子数据的应用,应增加该值。 |
| `--spawn-db` / `--spawn-db-env VAR` | 启动一个与目标引擎匹配的临时 DB(Docker Postgres/MySQL/Mongo,或 SQLite 文件),并通过 `VAR`(默认 `SQLITE_DB`)将其交给目标;运行结束后销毁。 |
| `--spawn-db-kind KIND` | 强制指定临时引擎(`sqlite`/`postgres`/`mysql`/`mongo`),而不是从源码自动检测。对于任何具有 SQLite 模式的应用,`sqlite` 是无需依赖的选择 — 不需要 Docker,也不需要端口配置。 |
| `--db-url URL` | 一个现有的临时 SQLAlchemy URL,用于在其中进行 provision(使用 `postgresql+psycopg2://…`)。 |
| `--provision N` / `--provision-admins N` | 将 N 个低权限(以及 N 个管理员)测试用户直接插入 DB,这样即使自注册关闭,BOLA/IDOR/BFLA 检查也能拥有真实的跨租户测试主体。 |
| `--no-mint` | 即使恢复了签名密钥,也不要生成具有 API 作用域的 JWT。 |
| `--no-attacker` | 不要自行注册一个一次性的低权限攻击者账户。 |
| `--safe` | 跳过所有会进行修改/破坏性的探测。 |
| `--only KEYS` / `--skip KEYS` | 要包含/排除的、以逗号分隔的模块 key。 |
| `--fail-on LEVEL` | CI 门禁严重级别(`none,info,low,medium,high,critical`;默认 `high`)。 |
| `--baseline findings.json` | 抑制已知的发现结果;仅对新发现进行门禁判定。 |
| `--discover-only` | 打印发现的配置信息(路由、认证、密钥)并退出 — 不进行攻击。 |
| `--list-modules` | 列出已注册的模块并退出。 |
| `--i-have-authorization` | 允许非环回目标(仅限授权使用)。 |
| `--out DIR` / `--no-color` | 报告输出目录(默认 `./heimdall-report`)/ 禁用 ANSI 颜色。 |
#### Provision 与一次性目标
针对注册功能关闭的应用进行深度运行(或为了对*许多*不同的所有者进行访问控制检查),请让 Heimdall 构建整个环境:
```
# 将应用启动到一个一次性 DB 上,seed 真实 principal,然后进行 attack——全部为 disposable:
heimdall --url http://127.0.0.1:8100 --source /path/to/App \
--launch '/path/to/App/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8100' \
--launch-cwd /path/to/App \
--spawn-db \
--provision 3 --provision-admins 1 \
--launch-timeout 300
```
将 `--launch` 指向目标*自己*的解释器(例如其 `.venv/bin/uvicorn`),以便启动命令能解析应用的依赖,并为在首次启动时进行迁移/种子数据填充的应用提供足够宽裕的 `--launch-timeout`。
`--provision` 会插入不同的用户(按照应用自身模型期望的方式对密码进行哈希处理),并通过真实的登录流程让每个用户登录,从而为 `a01` BOLA/IDOR/BFLA 探测提供真实的跨用户测试主体。结合 `--spawn-db` / `--launch`,整个评估过程 —— 服务器、数据库、用户 —— 都是围绕单个命令创建和销毁的。
如果应用内置了 **SQLite 模式**,请添加 `--spawn-db-kind sqlite` — 这是无需依赖的一次性方案(不需要 Docker,也不需要端口配置)。否则,`--spawn-db` 会自动检测引擎。
更倾向于使用 **服务器引擎**(应用真正的后端)?请改用 `--spawn-db-kind postgres`(或 `mysql`)— Heimdall 会启动一个一次性的 Docker 服务器,从其源码中读取应用实际使用的 DB 连接变量(环境变量*以及* pydantic-settings / Django 风格的字段),并将应用指向该一次性实例(当应用没有单独的端口变量时,会将映射的端口映射到宿主机上)。如果找不到可覆盖的单一连接变量,它会**拒绝执行**,而不是让应用启动并连接到其真实的数据库 —— 因此一次性运行永远不会触及生产数据。
### 库
```
import heimdall
result = heimdall.assess(
base_url="http://127.0.0.1:8000",
source_path="/path/to/YourApp", # optional white-box
credentials=[("admin", "admin", "admin@you.io", "hunter2")], # label,role,id,pw
safe=False, # True → skip destructive probes
only={"a01", "a02"}, # or skip={"race", "cmdi"}
)
print(result.counts()) # {'CRITICAL': 1, 'HIGH': 3, 'SAFE': 9, ...}
print(result.report_paths) # (findings.json, REPORT.md, REPORT.html, findings.sarif)
```
单独驱动发现过程:
```
profile = heimdall.discover("http://127.0.0.1:8000", source_path="…")
print(heimdall.summarize(profile))
```
## 模块
26 个检测器,按 OWASP 分类进行分组。运行 `heimdall --list-modules` 查看实时的注册表。标记为 **⚡** 的模块是*破坏性的*(它们会修改状态),并在 `--safe` 模式下被跳过。
| Key | 标题 | 功能描述 |
|---|---|---|
| **A01 — 失效的访问控制** | | |
| `a01` | 访问控制 / IDOR | 对受保护路由的未授权访问;admin 路由上的 BFLA;跨所有者的 object-by-id 路由上的 BOLA/IDOR |
| `csrf` | 跨站请求伪造 (CSRF) | 在 cookie-session 应用上:session-cookie `SameSite` + anti-CSRF-token 强制校验(token 认证时自动跳过) |
| `data-exposure` | 过度数据暴露 | 响应中的密钥/PII/其他用户的 token(具备自身 token 和公共元数据感知能力) |
| `mass-assignment` ⚡ | 批量赋值 | 在创建/更新时过度提交特权字段(`is_admin`、`role`),并带有确定性判定机制 |
| `oidc` | OAuth / OIDC 流程 | 发现的 OAuth 流程上的 `state`/PKCE/`redirect_uri` 处理 |
| `open-redirect` | 开放重定向 | 导向站外的重定向参数(像浏览器一样解析,而不是通过子字符串匹配) |
| **A02 — 加密机制失效** | | |
| `a02` | JWT 伪造 | `alg:none` 伪造 + 弱 HS256 密钥破解,*通过实时接受验证来证明*;query 中的 token 泄露 |
| **A03 — 注入** | | |
| `a03` | 注入 | SQLi(报错/布尔型,受可重复性限制)+ 反射型 XSS + SSTI + 路径遍历 + 操作符注入 |
| `sqli-blind` ⚡ | 盲注 SQLi | 基于时间的盲注 SQL 注入 |
| `cmdi` ⚡ | OS 命令注入 | 基于时间的 OS 命令注入 |
| `xxe` ⚡ | XML 外部实体 (XXE) | 在接受 XML 的路由上进行 XXE 文件泄露(结构化的 passwd 行匹配) |
| `sast` | SAST → DAST 链接 | 源码-汇聚点扫描,其发现结果会针对正在运行的应用进行实时重探测 |
| **A04 — 不安全设计** | | |
| `business-logic` ⚡ | 数值滥用 | 负数/溢出数量 & 价格/金额篡改 |
| `race` ⚡ | 竞态 / TOCTOU | 并发双重消耗;仅标记*存在分歧的*(累积的)竞态,而非幂等的竞态 |
| `workflow` ⚡ | 多步骤重放 | 重放某个步骤以获得双重效果 |
| `resource-consumption` | 资源消耗 | 无限制的分页 / payload 大小 / 缺失速率限制 |
| **A05 — 安全配置错误** | | |
| `a05` | 配置错误 | CORS 反射、缺失的安全响应头、文档暴露、stack-trace/调试信息泄露 |
| `host-header` | Host 头攻击 | 反射到 URL 中的 Host/`X-Forwarded-Host` 投毒 |
| `improper-inventory` | 敏感路径 | 暴露的 `.env`/配置/备份/VCS 及未记录的管理界面 |
| `graphql` | GraphQL 暴露 | 自省、建议、未授权查询 |
| `websocket` | WebSocket 安全 | 发现的 WS endpoint 上的 Origin/认证强制校验 |
| `file-upload` ⚡ | 无限制上传 | 上传接收点接受危险文件类型 |
| **A06 — 易受攻击和过时的组件** | | |
| `a06` | 过时组件 | `pip-audit` + 启发式版本检查(需要 `--source`) |
| **A07 — 身份识别和认证失败** | | |
| `a07` | 认证失败 | 登录速率限制 + XFF 绕过、用户枚举、弱密码、针对 OAuth-token endpoint 的锁定 (429/423) |
| `session` | Session 生命周期 | Token/session 过期、注销失效、轮换 |
| **A10 — SSRF** | | |
| `a10` | SSRF | URL 接收点发现 + 内部目标 / 云元数据探测 |
每个模块还会输出 **TESTED-SAFE** 发现,以便报告能够区分*已验证安全*和*未经测试*的项目。
## 输出
每次运行都会将结果写入 `heimdall-report/`:
- `REPORT.md` — 执行摘要、**攻击链**、每个发现的 OWASP 映射、指示性的 CVSS、证据/PoC、复现步骤、参考和工具。
- `REPORT.html` — 与上方相同,独立且带样式(可共享)。
- `findings.json` — 机器可读格式。
- `findings.sarif` — 用于 GitHub/GitLab/Azure 代码扫描的 SARIF 2.1.0(真实的发现记录为 `kind:fail`,TESTED-SAFE 记录为 `kind:pass`)。
## CI 集成
```
# 任何 finding 达到或超过阈值(默认:high)即让 build 失败
heimdall --url http://127.0.0.1:8000 --source . --fail-on high
# regression gate:仅对 baseline 报告中尚未存在的 finding 失败
heimdall --url http://127.0.0.1:8000 --baseline known-findings.json --fail-on medium
```
`--fail-on {none,info,low,medium,high,critical}` 设置退出码门禁;`--baseline ` 抑制已知/已接受的发现,从而确保 CI 仅在出现*新*发现时中断。通过 `github/codeql-action/upload-sarif` 上传 `findings.sarif`,即可在 Security 标签页中展示结果。
## 尝试一下 — 内置的漏洞演示应用
本仓库提供了一个故意设计为不安全的 FastAPI 应用,让你无需将其指向你自己的任何应用,就能看到 Heimdall 的端到端工作过程:
```
pip install -e '.[demo]'
uvicorn examples.vulnerable_app.main:app --host 127.0.0.1 --port 8099
heimdall --url http://127.0.0.1:8099 --source examples/vulnerable_app \
--cred admin:admin:admin:admin123 --cred alice:user:alice:alice123
```
一次干净的运行会 **~1 个 CRITICAL + 7-8 个 HIGH** 级别的问题 —— 包括 JWT 密钥伪造、BOLA/IDOR、BFLA、反射型 XSS、SSRF、带有凭据的 CORS、PII/密钥泄露等 —— 同时也会对该应用少数正确的 endpoint 给出 TESTED-SAFE 的判定。每一个发现都对应 [`examples/vulnerable_app/README.md`](examples/vulnerable_app/README.md) 中记录的一个植入漏洞。
## 安全性与范围
- **护栏机制:** 除非你传递 `--i-have-authorization` 参数,否则 Heimdall 会拒绝任何非环回目标。
- `--safe` 会跳过所有修改性/破坏性的探测。
- 报告可能包含密钥和目标内部信息 —— 仓库的 `.gitignore` 已将其排除;请勿将其纳入版本控制。
### ⚖️ 仅限授权使用
这是一款安全测试工具。**请仅针对你拥有的,或已获得明确、事先书面授权进行测试的系统使用此工具。** 在大多数司法管辖区,未经授权扫描或利用你不拥有的系统是非法的(例如美国《计算机欺诈和滥用法》、欧盟第 2013/40/EU 号指令、英国《1990 年计算机滥用法》及其他同等法律)。使用本软件即表示你确认你已获得对每个目标的必要授权,并自行承担使用责任;作者不对任何滥用行为承担责任。完整的免责声明请参阅 [LICENSE](LICENSE)。
## 工作原理概览
```
heimdall/
discovery/ openapi → RouteMap · auth detection (token/cookie) · JWKS · source secret scan → AppProfile
bootstrap/ launch target · spawn throwaway DB · provision users · mint principals via the real login flow
modules/ 26 detectors, each reading the AppProfile — no hard-coded paths
core/ Context, Finding, report renderer (MD/HTML/SARIF), attack-chain builder, loopback guardrail
runner.py launch → discover → bootstrap → modules → report
```
## 状态
Alpha 阶段。发现层主要针对 FastAPI/OpenAPI 3.x;漏洞利用模块以黑盒优先,并且对误报保持谨慎(未确认的 SSRF 接收点、启发式枚举等均被标记为需要手动/OAST 确认)。包含 60 多个用例的测试套件 (`pytest`) 锁定了每个模块的精确度 —— 每一个误报修复都会附带一个漏报对照组和一个回归测试。
标签:AV绕过, CISA项目, FastAPI, Web安全, 密码管理, 蓝队分析, 请求拦截, 逆向工具