删除 10 篇已完成/已实施的开发计划文档(认证独立化、captcha/confs C++ 重写、services.yaml、pybot 迁移、aibox --once/工具分层/CLI 化/ 重构快照、actpred cv2.LUT 优化),同步修复 ca/captcha2/pybot/aibox README、代码注释、安全审计与报告中的 12 处引用,MODULES.md 文档 计数更新为 67 篇。
122 lines
5.1 KiB
Markdown
122 lines
5.1 KiB
Markdown
# captcha 模块安全审计报告
|
||
|
||
**审计日期**: 2026-08-01
|
||
**审计范围**: `captcha_service.py`、`log_client.py`
|
||
**代码版本**: dev_qing 分支
|
||
|
||
---
|
||
|
||
## 代码验证记录
|
||
|
||
**验证日期**: 2026-08-03
|
||
**验证方式**: 逐条对照审计报告与当前代码(`captcha_service.py`、`log_client.py`、`_run.sh`)
|
||
|
||
### 验证结果汇总
|
||
|
||
| 等级 | 总数 | 已修复 | 部分修复 | 未修复 | 修复率 |
|
||
|------|------|--------|----------|--------|--------|
|
||
| P0 | 0 | 0 | 0 | 0 | - |
|
||
| P1 | 1 | 1 | 0 | 0 | 100% |
|
||
| P2 | 1 | 0 | 0 | 1 | 0% |
|
||
| **合计** | **2** | **1** | **0** | **1** | **50%** |
|
||
|
||
### 逐条验证
|
||
|
||
| 编号 | 状态 | 代码位置 | 验证说明 |
|
||
|------|------|----------|----------|
|
||
| P1-1 | ✅ 已修复 | `captcha_service.py` L227-232 | 新增 `MAX_STORE_SIZE`(默认 10000,可配置 `max_store`/`CAPTCHA_MAX_STORE`),`_handle_image` 在加锁后先清理过期项,再检查容量,超限拒绝生成并返回错误,防止内存耗尽 |
|
||
| P2-1 | ❌ 未修复 | `captcha_service.py` L128 | 仍为进程内存 dict,未迁移至 Redis;当前单实例可接受 |
|
||
|
||
---
|
||
|
||
## 修复进度
|
||
|
||
| 优先级 | 总数 | 已修复 | 待修复 |
|
||
|--------|------|--------|--------|
|
||
| P0 | 0 | 0 | 0 |
|
||
| P1 | 1 | 1 | 0 |
|
||
| P2 | 1 | 0 | 1 |
|
||
|
||
---
|
||
|
||
## 🟠 P1 — 高危问题
|
||
|
||
| # | 问题 | 说明 |
|
||
|---|------|------|
|
||
| P1-1 | ~~验证码存储无容量限制,大量生成可耗尽内存~~ | ✅ 已修复(2026-08-04):新增 `MAX_STORE_SIZE`(默认 10000),`_handle_image` 清理过期后容量仍满则拒绝生成并返回 `too many pending captchas`,防止内存耗尽 |
|
||
|
||
---
|
||
|
||
## 🟡 P2 — 中危问题
|
||
|
||
| # | 问题 |
|
||
|---|------|
|
||
| P2-1 | 内存存储不支持多实例水平扩展(需换 Redis),当前单实例可接受 |
|
||
|
||
---
|
||
|
||
## ✅ 已有安全机制
|
||
|
||
1. ✅ **一次性使用**: verify 后立即 `pop` 删除 Token(`captcha_service.py` L231)
|
||
2. ✅ **5 分钟过期**: 惰性清理(`captcha_service.py` L213-215)
|
||
3. ✅ **常数时间比较**: XOR 防时序攻击(`captcha_service.py` L239-245)
|
||
4. ✅ **仅监听 127.0.0.1**: 不对外暴露(`captcha_service.py` L181)
|
||
5. ✅ **gateway 层代理**: `Cache-Control: no-store` 禁止缓存验证码图片
|
||
6. ✅ **依赖 pymsg 协议**: recv_timeout 防 Slowloris
|
||
7. ✅ **图形验证码使用 PIL 生成**: 不依赖外部服务
|
||
8. ✅ **两层配置加载**: confs 拉取 `captcha.ini` + 环境变量覆盖(`captcha_service.py` L46-113)
|
||
9. ✅ **配置白名单合并**: `_merge_ini` 仅覆盖已知 section/key,防止意外字段注入(`captcha_service.py` L51-65)
|
||
10. ✅ **配置完整性校验**: 缺失必填项时启动失败(`captcha_service.py` L103-112)
|
||
11. ✅ **confs retry_on_refused**: confs 未就绪时自动阻塞重试(`captcha_service.py` L76-77)
|
||
12. ✅ **Token 使用 secrets.token_hex**: 加密安全随机(`captcha_service.py` L207)
|
||
13. ✅ **log_client 异步批量 + 队列上限**: `QUEUE_MAXSIZE=10000`,队列满时丢弃最旧条目(`log_client.py` L38)
|
||
14. ✅ **log_client 异常安全网**: `_on_error` 捕获 handler 外异常,线程不崩溃(`log_client.py` L150-153)
|
||
|
||
---
|
||
|
||
## 代码审查发现
|
||
|
||
### NEW-1: 验证码答案使用 random 模块生成(P2)
|
||
|
||
- **位置**: `captcha_service.py` L146
|
||
- **问题**: `generate_text()` 使用 `random.choices` 而非 `secrets` 模块生成验证码答案。`random` 模块是确定性伪随机,若攻击者能推测随机种子状态,可预测验证码答案
|
||
- **影响**: 低(Token 使用 `secrets.token_hex` 保护,攻击者需先获取有效 Token)
|
||
- **建议**: 将 `random.choices` 替换为 `secrets.SystemRandom().choices` 或逐个调用 `secrets.choice`
|
||
|
||
### NEW-2: 验证码图片生成无速率限制(P1-1 补充)
|
||
|
||
- **位置**: `captcha_service.py` L204-222
|
||
- **问题**: `_handle_image` 无任何速率限制,且 PIL 图片生成是 CPU 密集型操作,高频调用不仅消耗内存,还消耗 CPU
|
||
- **建议**: 添加滑动窗口限流(如单 IP 每分钟最多 10 次),与 smtp 模块对齐
|
||
|
||
---
|
||
|
||
## 修复路线图
|
||
|
||
### 短期
|
||
- [x] 添加验证码存储容量上限(默认 10000,超出时拒绝新生成)✅ 已修复(2026-08-04)
|
||
- [ ] 添加生成速率限制(单 IP 每分钟最多生成 N 个)
|
||
- [ ] 将 `generate_text()` 中的 `random.choices` 替换为 `secrets` 模块
|
||
|
||
### 中期
|
||
- [ ] 考虑替换为 Redis 存储支持水平扩展(当前单实例足够)
|
||
|
||
---
|
||
|
||
## C++20 重写
|
||
|
||
2026-08-09,captcha 模块已完成 C++20 重写(`captcha2/`),使用 FreeType + stb_image_write
|
||
替代 Pillow,协议完全兼容,gateway 零改动。
|
||
|
||
- 重写审计报告: [captcha2_SECURITY_AUDIT_20260809.md](captcha2_SECURITY_AUDIT_20260809.md)
|
||
- `core/init.txt` 已切换为 `captcha2/_run.sh`
|
||
|
||
本报告中的遗留问题在 C++ 版中的状态:
|
||
|
||
| 原审计项 | C++ 版状态 |
|
||
|----------|-----------|
|
||
| P1-1 存储容量上限 | ✅ 继承(max_store=10000) |
|
||
| P2-1 Redis 水平扩展 | ❌ 未实现(单实例) |
|
||
| NEW-1 答案非安全随机 | ❌ mt19937(同源问题,C++ 审计 P2-1) |
|
||
| NEW-2 生成速率限制 | ⚠️ 已实现但为全局桶(C++ 审计 P1-1) |
|