DreadpiratePickles/key-kettle
GitHub: DreadpiratePickles/key-kettle
一款基于 NIST/OWASP/CISA 指南对密码策略进行评分审计的离线 CLI 工具,输出带来源引用的结构化改进报告。
Stars: 0 | Forks: 0
# 🫖 Key Kettle
### 根据现代 NIST / OWASP / CISA 指南审计密码策略要求。
    
*“一个大写字母、一个数字、一个符号”——正是这条规则导致了 `P@ssw0rd1` 被使用了十亿次。*
Key Kettle 接收以 JSON 表示的密码策略,并返回一份经过评分、定级和按优先级排序的报告:存在什么问题、如何修复、*为何重要*,以及是哪项标准的要求。这是一款你在客户会议前运行的工具,这样你就可以直接提交“这里有 6 项未通过的控制措施,并按严重程度排序”,而不是含糊地说“你们的密码规则感觉过时了”。
它是一个**防御性的、离线的**咨询工具。它只读取策略*描述*——绝不接触目录、身份验证系统或真实密码。唯一的网络暴露面是可选的本地报告 UI,且该功能受到限制(参见[安全与授权](#safety--authorization))。
## 开发初衷
现实中大多数密码策略仍然包含当前指南明确不鼓励的控制措施:最大长度过短、强制定期轮换、死板的组合规则、禁止粘贴/密码管理器,以及使用快速的通用哈希进行存储。Key Kettle 将这些要求转化为符合标准的改进计划,让合规顾问、MSP 或内部安全团队能够直接付诸行动。
每一项发现都引用了其来源:
- [NIST SP 800-63B](https://pages.nist.gov/800-63-4/sp800-63b.html) — 长度优先于组合,无强制轮换,黑名单筛选,速率限制,慢速哈希。
- [OWASP Authentication / Password Storage Cheat Sheets](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html) — 具体实现细节。
- [CISA Multifactor Authentication](https://www.cisa.gov/topics/cybersecurity-best-practices/multifactor-authentication) — 强调 MFA。
- [Verizon DBIR](https://www.verizon.com/business/resources/reports/dbir/) — 为什么凭证滥用始终是攻击者的实用路径。
## 工作原理
```
policy JSON ──▶ PasswordPolicy.from_dict ──▶ analyze_policy ──▶ PolicyReport
(validate + coerce + (one check per (score, grade,
fill weak defaults) control) summary, recs)
│ │
├─ policy_key_warnings ──▶ stderr notes ├─ rich table/panel (humans)
│ └─ pure JSON (machines)
```
**1. 解析与验证 (`policy.py`)。** 输入被视为不可信的敌对数据。字段被强制转换为其真实类型(布尔值接受 `true`/`"yes"`/`1`,轮换接受 `0`/`""`/`null` 作为“禁用”),检查范围(`min_length` 在 `1..4096` 之内,`max_length ≥ min_length`,无非负值或荒谬的值),错误的输入会引发 `PolicyError` 并指出出错字段。**缺失的字段会故意回退到*脆弱的*示例**——审计工具应对未告知的控制措施做最坏的假设,而不是凭空给出一个看似美好的默认值。未知/拼写错误和省略的字段将作为非致命提示输出到 stderr。
**2. 分析 (`analyzer.py`)。** 评估十一项控制措施,每项恰好生成一个建议——`pass` 或某个问题——因此输出是一份完整的清单,而不仅仅是一堆抱怨:
| 控制措施 | 通过条件 | 失败时的权重 |
| --- | --- | --- |
| 最小长度 | ≥ 15 (如果要求 MFA 则 ≥ 8) | high |
| 最大长度 | ≥ 64 | medium |
| 组合规则 | 无要求 | medium (建议) |
| 定期轮换 | 无 | medium/low (建议) |
| 泄露密码筛查 | 启用 | high |
| 多因素认证 | 必须 | high |
| 密码管理器与粘贴 | 均允许 | medium |
| 速率限制 | 1–10 次失败尝试 | high |
| 密码存储 | 加盐哈希 | **critical** |
| 密码哈希算法 | Argon2id / bcrypt / scrypt / PBKDF2 | high (建议) |
| 字符允许范围 | 空格 + Unicode | low (建议) |
**3. 评分与定级。** 从 100 开始,减去每项未通过控制措施的严重性权重(`critical 28, high 18, medium 10, low 4`),下限为 0。等级划分:`A ≥ 90`, `B ≥ 80`, `C ≥ 70`, `D ≥ 60`,否则为 `F`。在表格和 JSON 中,建议均按最差优先排序。
**4. 渲染。** 人类将获得丰富的摘要面板 + 颜色编码的表格(严重性 `critical/high → 红色`,`medium → 黄色`,`low → 青色`,`pass → 绿色`)。机器将获得纯 JSON。两者绝不混用。
### 数据模型
`PasswordPolicy`(不可变数据类,无数据库)捕获:`min_length`,`max_length`,四个 `require_*` 组合标志,`rotation_days`,`breach_screening`,`mfa_required`,`paste_allowed`,`password_manager_allowed`,`lockout_threshold`,`stores_hashed`,`hashing_algorithm`,`allows_spaces`,`allows_unicode`。运行 `key-kettle sample-policy` 以查看完整结构。
## 安装
```
cd key-kettle
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e . # provides the `key-kettle` command
cp .env.example .env # optional: sets default serve host/port
```
不想进行可编辑安装?所有命令均可通过 `PYTHONPATH=src python -m key_kettle.cli ...` 运行。
## CLI 用法
全局参数:`--plain` / `--no-color` 禁用颜色、emoji 和表格绘制(当设置了 `NO_COLOR` 或输出不是 TTY 时也会自动生效)。`--version` 打印版本号。无论这些设置如何,JSON 输出始终是纯净的。
### `sample-policy` — 打印策略以供编辑
```
key-kettle sample-policy # a deliberately dated weak baseline
key-kettle sample-policy --strong # a modern, NIST-aligned baseline
key-kettle sample-policy > policy.json
```
将策略 JSON 打印到 stdout(品牌标头(如果有)会输出到 stderr,因此 JSON 保持可通过管道传输)。
### `analyze` — 对策略进行评分
```
key-kettle analyze --policy policy.json # human report
key-kettle analyze --policy - < policy.json # read from stdin
key-kettle sample-policy | key-kettle analyze --policy - # pipe straight in
key-kettle analyze --policy policy.json --json | jq # machine-readable
key-kettle analyze --policy policy.json --fail-under 80 # stricter CI gate
```
| 标志 | 含义 |
| --- | --- |
| `--policy PATH` | 策略 JSON 文件,或 `-` 表示 stdin(必填)。文件大小限制为 1 MiB。 |
| `--json` | 向 stdout 输出纯 JSON(无颜色,无标头)。 |
| `--fail-under SCORE` | 如果分数 < SCORE,则以非零状态退出(默认为 70)。 |
**退出代码:** `0` = 分数达到阈值;`1` = 低于阈值*或*输入错误(文件缺失、JSON 错误、字段无效)。非常适合作为 CI 的检查关卡。
人类可读的输出示例(强密码策略):
```
┌───────────────────────── Audit result ─────────────────────────┐
│ 100/100 grade A │
│ 0 failing controls, 0 warnings. │
│ 0 failing · 0 advisory · 11 passing · 11 controls reviewed │
└─────────────────────────────────────────────────────────────────┘
Sev Control Finding Recommended fix
─────────────────────────────────────────────────────────────────────────────
✓ pass Multi-factor authentication MFA is required. Keep MFA required…
✓ pass Rate limiting Failed attempts… Keep tight rate…
…
```
对于弱密码策略,同一视图会将最严重的问题展示在最前面:
```
X high Compromised-password screening No blocklist… Compare new passwords…
X high Minimum length Minimum length 8… Set minimum length to 15…
X high Multi-factor authentication MFA is not req… Require MFA…
```
### `serve` — 本地报告 UI
```
key-kettle serve # http://127.0.0.1:5065
key-kettle serve --host 127.0.0.1 --port 5065
```
打开一个 Flask 页面,你可以在其中粘贴策略 JSON 并获取渲染后的报告。默认绑定到环回地址。绑定到其他任何地址均需要明确确认(见下文)。
## 安全与授权
Key Kettle 用于**审计你拥有或被授权评估的策略**。它不执行任何扫描,也不发送任何电子邮件。唯一需要关注的风险面是 `serve`:
- **默认绑定到 `127.0.0.1`。** 报告 UI *没有身份验证*,并会评估任何能访问到它的人粘贴的策略 JSON。
- **非环回绑定受到限制。** 除非你传递 `--allow-nonlocal`(这是一种明确的“我拥有此网络并接受风险”的确认),否则 `serve --host 0.0.0.0`(或任何局域网 IP / 主机名)将被拒绝。拒绝时的退出代码为 `2`。
- **在非环回主机上使用 `--debug` 总是被拒绝的** —— Werkzeug 交互式调试器允许远程代码执行。
- **输入被视为不可信。** 读取文件大小受限(CLI 1 MiB / HTTP 正文 256 KiB),非对象和超出范围的 JSON 将被拒绝并返回整洁的错误信息,错误响应绝不会泄露堆栈跟踪。输出由 Jinja 自动转义,并带有 `X-Content-Type-Options`、`X-Frame-Options`、`Referrer-Policy` 和严格的 `Content-Security-Policy`。
- **不会读取或记录任何机密。** `.env` 仅保存默认的主机/端口。对于笔记本电脑以外的任何实际部署,请在前面部署真实的 WSGI 服务器和身份验证系统。
## 开发与测试
```
cd key-kettle
PYTHONPATH=src python -m pytest -q
```
测试快速且完全离线(无网络,无睡眠):Flask 端点通过进程内测试客户端进行测试。测试范围涵盖分析器(评分、定级边界、全清单不变性)、策略验证器(范围和类型拒绝、弱默认填充、关键警告)、CLI(退出代码、JSON 纯净度、文件/stdin 处理、大小上限、环回限制)以及应用程序(错误输入返回 400 而非 500、超大返回 413、安全标头)。
**布局**
```
key-kettle/
src/key_kettle/
policy.py # PasswordPolicy dataclass, validation, sample baselines
analyzer.py # 11 controls → scored PolicyReport
ui.py # shared rich theme, banner, report renderer
cli.py # sample-policy / analyze / serve
app.py # Flask JSON input + report UI (hardened)
templates/
tests/
```
## 🏷️ 为什么叫 "Key Kettle"?
把策略放在壶里煮沸,看看能剩下什么。大多数密码规则都是在合规文档之间流传的民俗,它们的目标是“看起来很严格”而不是“真正很强”。NIST 在 2017 年重写了其指南;令人吃惊的是,大量的密码策略根本没收到通知。该工具根据从 NIST、OWASP 和 CISA 提取的 11 项控制措施来审计你的策略——并为每一个问题都引用了来源,这样在会议开始之前,你就已经赢得了关于修复方案的争论。
## 🔬 此工具的构建方式
**目的。** 一款密码策略审计工具,其输出像一份完整的、按优先级分诊排序的清单,而不是一堆抱怨。与 NIST/OWASP/CISA 对齐的 11 项控制措施中的每一项都会报告通过或失败,并附带引用的修复方案。
**工作原理。** 它接收一个策略(JSON 文件、stdin 或生成的 `sample-policy`),验证并强制转换字段,评估全部 11 项控制措施,对结果进行评分和定级,并按最差优先对建议进行排序。相同的数据驱动着 CLI 表格、JSON 和本地报告 UI。
**出色的 CLI。** 带有评分/定级摘要面板的颜色编码、按分诊排序的表格;对于机器命令,横幅会输出到 stderr,从而保持 stdout 可通过管道传输;`--policy -` 从 stdin 读取,因此 `sample-policy | analyze --policy -` 可以正常工作;而 `--fail-under SCORE` 将 `analyze` 变成了一个可调节的 CI 检查关卡。
**关键改进。** *功能性:* 审计现在会将**每一项**控制措施报告为通过或失败(共 11 项),而不是仅仅列出问题,因此你可以看到完整的安全态势;对范围和类型进行严格的 `PolicyError` 验证;真实世界的类型强制转换(布尔字符串,`0`/`""`/`null` 作为禁用的轮换);扩展了 `GOOD_HASHES` 以包含 argon2i/argon2d。*安全性:* `serve` 拒绝在没有 `--allow-nonlocal` 的情况下进行非环回绑定(UI 没有身份验证且会评估粘贴的 JSON),并拒绝在环回网络之外使用 `--debug`;`MAX_CONTENT_LENGTH` 限制为 256 KiB 并在处理器内进行二次检查;CLI 将读取大小限制在 1 MiB;严格的 CSP 以及标准标头集。
**示例。**
```
PYTHONPATH=src python -m key_kettle.cli sample-policy --strong \
| PYTHONPATH=src python -m key_kettle.cli analyze --policy -
```
## ⚖️ 授权使用与安全准则
**这些是用于你拥有或被明确授权评估的系统、文件、网络和人员的防御性工具。** 在运行任何程序之前,请阅读本声明:
- **授权不是可选的。** 钓鱼演练、网络扫描、IP 信誉查询和 Web 应用程序探测都会涉及他人的系统或数据。请首先获得书面授权。有几种工具在你声明之前*拒绝执行任何操作*(`--yes`, `--authorized-training`, `--i-have-authorization`, `--i-am-authorized` 等)。
- **默认安全。** 每个 Web UI 都绑定到 `127.0.0.1` (环回网络)。出站流量、实时发送和主动扫描都被限制在明确的标志之后——空运行 (dry-run)、被动模式或拒绝并警告始终是默认设置。
- **避免意外的自毁操作。** Flask `--debug`(Werkzeug 交互式调试器在任何堆栈跟踪上都可以执行远程代码执行)会受到明确的警告,并且在环回网络之外会被完全拒绝。不可信的输入受到大小限制和验证,并被无害化渲染,因此充满恶文件或日志行不会导致崩溃——或接管——你的终端。
- **输出中不含机密。** API key 保留在请求标头中,密码来自环境变量,不会记录或打印任何敏感信息。
这些不是攻击性工具。它们不包含任何漏洞利用、凭证收集器或 payload。如果某个工具*可能*被滥用,那么它在构造上就被设计为能够抵御此类滥用。
## 🧪 开发
```
python -m venv .venv && source .venv/bin/activate
pip install -e .
pytest -q # 49 tests, no network, no sleeps
key-kettle --help
```
## 📄 许可证
基于 **MIT License** 发布。参见 [LICENSE](LICENSE)。
防御性工具。不包含漏洞利用、payload 或凭证收集器。
标签:Python, Web界面, 安全合规, 安全基线检查, 密码策略审计, 无后门, 网络代理, 逆向工具