Files
micro_servers/docs/security/db_SECURITY_AUDIT_20260801.md
T
qing 5fbe3ed5e4 docs(security): 更新全部模块审计报告,添加代码验证记录
逐模块对照实际代码验证审计报告中的问题修复状态,添加代码验证记录、逐条验证结果、修复率统计。合并aibox两份审计报告,删除重复文件。修复率:confs 61% > dnfs 60% > ai_review 50% > smtp 37.5% > db 33% > core 12.5% > gateway 12.5% > pymsg 6.25% > static 5% > captcha/aibox/BotOps 0%
2026-08-03 14:12:45 +08:00

129 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# db 模块安全审计报告
**审计日期**: 2026-08-01
**审计范围**: `dbv2.py`、`db_tools.py`、`log_client` 相关
**代码版本**: dev_qing 分支
---
## 修复进度
| 优先级 | 总数 | 已修复 | 部分修复 | 未修复 |
|--------|------|--------|----------|--------|
| P0 | 1 | 0 | 1 | 0 |
| P1 | 3 | 0 | 1 | 2 |
| P2 | 2 | 1 | 0 | 1 |
| **合计** | **6** | **1** | **2** | **3** |
---
## 🔴 P0 — 严重问题
### P0-1: 零认证对外开放完整 CRUD(依赖 127.0.0.1 网络隔离)
- **位置**: `dbv2.py` L180、L191-196、L323-406
- **当前状态**: ⚠️ 部分修复
- ✅ 默认监听 `127.0.0.1`(`dbv2.py` L180),Docker 也绑定到 127.0.0.1
- ✅ 配置通过 confs + 环境变量两层加载,配置完整性校验(`dbv2.py` L118-129)
- ❌ 仍无任何认证机制(`RpcServer` 无 auth 回调)
- ❌ SELECT 无默认 LIMIT:`_do_select` (L364-366) limit 参数可选,客户端可省略以获取全表数据
- ❌ UPDATE/DELETE 不强制要求 WHERE:`_do_update` (L391-394) 和 `_do_delete` (L400-403) 仅在 where_cond 非空时添加 WHERE 子句,可执行无条件全表更新/删除
- ❌ 无表级/操作级权限控制
- **修复建议**:
1. ~~确保管理接口仅监听 127.0.0.1~~ ✅ 已实现
2. 添加 API Token 认证(预共享密钥,所有调用需携带 `_auth` 字段)
3. SELECT 强制添加 LIMIT 上限(默认 1000 条),防止拖库
4. 添加操作权限:日志写入只允许 insert,禁止 delete/truncate
5. 拒绝无条件 UPDATE/DELETE(必须带 where 条件)
6. DDL 操作仅限本地运维工具,RPC 接口完全禁用
---
## 🟠 P1 — 高危问题
| # | 问题 | 状态 | 说明 |
|---|------|------|------|
| P1-1 | db_tools.py 运维工具存在 SQL 字符串拼接风险 | ⚠️ 部分修复 | `db_tools.py` 使用参数化查询(`executemany` + 占位符),表名来自 `sqlite_master` 查询非用户输入;但 `_view_db.sqlite3.py` L53 `cur.execute(args.sql)` 支持自由 SQL(本地工具,可接受风险) |
| P1-2 | 无操作审计日志 | ❌ 未修复 | `_handle_execute` (L323-344) 处理 CRUD 操作时无任何审计记录,无法追溯谁在何时修改了什么数据 |
| P1-3 | Logs 表自动清理可被利用销毁证据 | ❌ 未修复 | `_do_cleanup` (L493-528) 按时间和条数清理,攻击者可通过大量写日志触发 `max_records` 裁剪,删除攻击痕迹 |
---
## 🟡 P2 — 中危问题
| # | 问题 | 状态 | 说明 |
|---|------|------|------|
| P2-1 | 日志表自动清理保留策略可配置化 | ✅ 已修复 | `dbv2.py` L65-69 通过 `[logs]` 配置段支持 `retention_days`、`max_records`、`cleanup_interval`,通过 confs/db.ini + 环境变量配置 |
| P2-2 | 错误信息可能泄露表结构/字段名给调用方 | ❌ 未修复 | `_coerce_value` (L262-265) 返回 `"列 {column.name} 的日期时间值无法解析..."` 暴露列名;`_handle_execute` (L332) 返回 `"表加载失败: {e}"` 暴露表名 |
---
## ✅ 已有安全机制
1. ✅ **SQLAlchemy Core 参数化查询**:核心 CRUD 路径使用表反射 + 参数化,零 SQL 注入风险 (`dbv2.py` L346-406)
2. ✅ **仅监听 127.0.0.1**:不对外暴露 (`dbv2.py` L180)
3. ✅ **集中式日志 fail-safe**:db 不可用时静默丢弃,不阻塞业务 (`example_log_client.py` L57-106)
4. ✅ **自动提交/回滚**:异常时自动回滚事务
5. ✅ **日期/时间适配**:ISO 8601 处理,`"$now"` 哨兵 (`dbv2.py` L242-287)
6. ✅ **日志自动清理**:后台线程按时间+条数清理,防止磁盘占满 (`dbv2.py` L480-528)
7. ✅ **log_client 健壮性**:异步队列、后台线程、fail-safe、队列上限 10000 (`example_log_client.py` L38-41)
8. ✅ **配置白名单校验**:`_merge_ini` 仅覆盖已知 section/key,防止意外字段注入 (`dbv2.py` L73-81)
9. ✅ **配置完整性校验**:启动时检查所有必需配置项,缺失则退出 (`dbv2.py` L118-129)
10. ✅ **SQLite PRAGMA 优化**:WAL 模式 + NORMAL 同步 + busy_timeout + mmap (`dbv2.py` L139-155)
11. ✅ **表反射线程安全**:double-check 锁机制防止并发反射竞态 (`dbv2.py` L225-239)
---
## 修复路线图
### 立即(24小时)
- [ ] SELECT 添加强制默认 LIMIT 上限(防止拖库)
- [ ] UPDATE/DELETE 强制执行 WHERE 条件检查
### 短期(72小时)
- [ ] 添加 API Token 认证
- [ ] 无条件 UPDATE/DELETE 拒绝执行
- [ ] 错误信息脱敏
### 中期
- [ ] 表级权限控制(日志表只写不删/改)
- [ ] 管理操作审计日志
- [ ] 日志清理防篡改(保留清理前的摘要/签名)
---
## 代码验证记录
**验证日期**: 2026-08-03
**验证方式**: 逐条对照审计报告与当前代码(`dbv2.py`、`db_tools.py`、`example_log_client.py`、`_view_db.sqlite3.py`)
### 验证结果汇总
| 等级 | 总数 | 已修复 | 部分修复 | 未修复 | 修复率 |
|------|------|--------|----------|--------|--------|
| P0 | 1 | 0 | 1 | 0 | 50% (部分) |
| P1 | 3 | 0 | 1 | 2 | 17% (部分) |
| P2 | 2 | 1 | 0 | 1 | 50% |
| **合计** | **6** | **1** | **2** | **3** | **33%** |
### 逐条验证
| 编号 | 状态 | 代码位置 | 验证说明 |
|------|------|----------|----------|
| P0-1 | ⚠️ 部分 | `dbv2.py` L180, L323-406 | 已绑定 127.0.0.1;但无认证、SELECT 无默认 LIMIT、UPDATE/DELETE 不强制 WHERE |
| P1-1 | ⚠️ 部分 | `db_tools.py` L166-169, `_view_db.sqlite3.py` L53 | `db_tools.py` 使用参数化查询;`_view_db.sqlite3.py` 支持自由 SQL(本地工具) |
| P1-2 | ❌ 未修复 | `dbv2.py` L323-344 | `_handle_execute` 无任何审计日志记录 |
| P1-3 | ❌ 未修复 | `dbv2.py` L493-528 | `_do_cleanup` 按时间/条数清理,可被攻击者利用 |
| P2-1 | ✅ 已修复 | `dbv2.py` L65-69 | `retention_days`/`max_records`/`cleanup_interval` 通过 confs 可配置 |
| P2-2 | ❌ 未修复 | `dbv2.py` L262-265, L332 | 错误信息暴露列名和表名 |
### 新增安全措施(审计报告未覆盖)
| 措施 | 代码位置 | 说明 |
|------|----------|------|
| 配置白名单校验 | `dbv2.py` L73-81 | `_merge_ini` 仅覆盖已知 section/key,防止意外字段注入 |
| 配置完整性校验 | `dbv2.py` L118-129 | 启动时检查所有必需配置项,缺失则退出 |
| SQLite PRAGMA 优化 | `dbv2.py` L139-155 | WAL + NORMAL 同步 + busy_timeout + mmap |
| 表反射线程安全 | `dbv2.py` L225-239 | double-check 锁机制防止并发反射竞态 |
| 日志队列上限 | `example_log_client.py` L41 | `_QUEUE_MAXSIZE = 10000`,满则丢弃最旧条目 |
| 后台线程异常安全网 | `example_log_client.py` L188-192 | 最外层 catch 防止异常杀死日志线程 |