5.6 KiB
5.6 KiB
审计记录 — Settings 安全加固 + UX 迭代
审计信息
- 日期: 2026-05-30
- 审计人: Claude (AI) + 用户确认
- 触发原因: 安全加固 + UX 迭代
审计范围
| 文件 | 行数 | 状态 |
|---|---|---|
| server/api/settings.py | 1278 | ☑ 已审 |
| server/api/auth.py | 372 | ☑ 已审 |
| server/application/services/auth_service.py | 576 | ☑ 已审 |
| web/app/settings.html | 938 | ☑ 已审 |
| web/app/login.html | 347 | ☑ 已审 |
审计8步结果
Step 1: 登记 ✅
Step 2: 全文Read ✅
Step 3: 规则扫描H
30 项基础检查 + 1 项额外检查 = 31 项
Step 4: Closure表
| 编号 | 项目 | 文件 | 严重度 | 判定 | 依据 |
|---|---|---|---|---|---|
| H-01 | SQL注入 | 全部 | - | 未命中 | SQLAlchemy ORM,无f-string拼SQL |
| H-02 | 命令注入 | 全部 | - | 未命中 | 无os.system/subprocess |
| H-03 | XSS | settings.html | - | 未命中 | esc()/escAttr()标准转义 |
| H-04 | SSRF TOCTOU | settings.py | LOW | ACCEPTED_RISK | 管理员接口、窗口极短、需控制DNS |
| H-05 | 路径穿越 | 全部 | - | 未命中 | 无文件系统操作 |
| H-06 | 明文密码 | settings.py | - | 未命中 | SENSITIVE_KEYS脱敏+reveal需密码 |
| H-07 | 硬编码密钥 | 全部 | - | 未命中 | 来自settings对象(.env+MySQL) |
| H-08 | 静默吞错 | auth.py | - | FALSE_POSITIVE | logger.warning+exc_info=True |
| H-09 | 静默吞错(hot-reload) | settings.py | LOW | FINDING→已修 | 改为logger.warning+跳过setattr |
| H-10 | 权限检查 | 全部 | - | 未命中 | JWT+Depends(get_current_admin) |
| H-11 | IP格式校验 | settings.py | MEDIUM | FINDING→已修 | IpAllowlistSaveRequest加model_validator |
| H-12 | 竞态条件 | settings.py | LOW | ACCEPTED_RISK | 管理员单人操作,概率极低 |
| H-13 | CSRF | 全部 | - | 未命中 | JWT Bearer不自动附加+SameSite cookie |
| H-14 | 边界条件 | settings.py | - | 未命中 | min_length/max_length保护 |
| H-15 | 类型转换 | auth_service.py | - | 未命中 | try/except包裹int() |
| H-16 | None检查 | 全部 | - | 未命中 | 关键None检查均已覆盖 |
| H-17 | 索引越界 | auth_service.py | - | 未命中 | HMAC-SHA1 digest长度足够 |
| H-18 | 递归/循环 | 全部 | - | 未命中 | MAX_REDIRECTS=3+range(-1,2) |
| H-19 | 资源泄漏 | 全部 | - | 未命中 | async with上下文管理 |
| H-20 | 时序问题 | settings.py | - | 未命中 | 毫秒级窗口,实际不可利用 |
| H-21 | N+1查询 | 全部 | - | 未命中 | 最多2-3次DB查询/请求 |
| H-22 | 同步阻塞DNS | settings.py | MEDIUM | FINDING→已修 | 改为asyncio.get_event_loop().getaddrinfo() |
| H-23 | 大数据 | 全部 | - | 未命中 | 全部分页+27行settings表 |
| H-24 | 内存使用 | 全部 | - | 未命中 | 无大对象常驻 |
| H-25 | 缓存 | 全部 | - | N/A | 内存热更新,无需额外缓存 |
| H-26 | 错误处理 | 全部 | - | 未命中 | HTTP状态码+detail消息一致 |
| H-27 | 日志 | 全部 | - | 未命中 | AuditLog+logger.error/warning |
| H-28 | 文档 | 全部 | - | 未命中 | 模块/类/函数级docstring |
| H-29 | 重复代码 | settings.py | LOW | FINDING→已修 | 提取_verify_reauth辅助函数 |
| H-30 | 一致性 | settings.py/html | LOW | FINDING→已修 | 统一catch→console.error+toast |
| H-31 | TOTP格式不一致 | auth.py | LOW | FINDING→已修 | totp_code加min_length=6 |
Step 5: 入口表 ✅
全部API端点已检查(GET/PUT/POST/DELETE路由)。
Step 6: 输入→Sink ✅
所有用户输入路径已追踪:
- PUT /{key} → IMMUTABLE_KEYS → MUTABLE_KEYS → SETTING_VALIDATORS → repo.set
- POST /manual → IpAllowlistRequest model_validator → repo.set
- DELETE /ip → query param ip → string comparison
- PUT /password → bcrypt.checkpw → TOTP verify → bcrypt.hashpw → DB
Step 7: 归类
server/api/settings.py 1278行 13H 4FINDING → 0FINDING (全部已修)
server/api/auth.py 372行 8H 1FINDING → 0FINDING (已修)
server/application/services/auth_service.py 576行 0H 0FINDING
web/app/settings.html 938行 10H 2FINDING → 0FINDING (全部已修)
web/app/login.html 347行 0H 0FINDING
────────────────────────────────────────────────────────────
总计 7 FINDING → 0FINDING (全部已修)
Step 8: DoD ✅
FINDING 列表
| 编号 | 严重度 | 描述 | 修复方式 |
|---|---|---|---|
| F-1 | MEDIUM | IpAllowlistSaveRequest.manual_ips 无IP格式校验 | 加model_validator复用_IP_RE+_DOMAIN_RE |
| F-2 | MEDIUM | socket.getaddrinfo同步阻塞事件循环 | 改为await asyncio.get_event_loop().getaddrinfo() |
| F-3 | LOW | hot-reload int转换失败静默pass | 改为logger.warning+跳过setattr |
| F-4 | LOW | re-auth模式4处完全重复 | 提取_verify_reauth()辅助函数 |
| F-5 | LOW | totp_code无长度约束 | 加min_length=6,max_length=6 |
| F-6 | LOW | revealTelegramToken空catch | 改为console.error+toast |
| F-7 | LOW | toggleApiKeyVisibility空catch | 改为console.error+toast |
结论
☑ 审计通过,7 FINDING 全部已修复,0 遗留,可部署
归类统计
| 严重度 | 数量 | 处理 |
|---|---|---|
| MEDIUM | 2 | 全部FINDING,已修复 |
| LOW | 5 | 全部FINDING,已修复 |
| ACCEPTED_RISK | 2 | H-04 SSRF TOCTOU + H-12 竞态条件 |
| FALSE_POSITIVE | 1 | H-08 auth.py Redis降级 |
| 未命中 | 22 | 安全基线良好 |