# 项目审查问题清单 审查日期:2026-05-01 本文档用于记录当前项目中已发现的高风险问题,并作为后续逐项修复的跟踪清单。状态说明: - `待处理`:尚未开始修复。 - `处理中`:已经开始改动或验证。 - `已修复`:代码已修复并通过基本验证。 - `暂缓`:因演示环境、硬件依赖或其他原因暂不处理。 ## 1. 优先级概览 | 编号 | 优先级 | 状态 | 模块 | 问题 | | --- | --- | --- | --- | --- | | R-001 | P0 | 已修复 | 服务端 | 公网接口无鉴权且允许任意来源 | | R-002 | P0 | 部分修复 | 全项目 | 明文密钥和凭据已进入项目文件 | | R-003 | P1 | 已修复 | 服务端 | `face_id` 可造成路径穿越写读删文件 | | R-004 | P1 | 已修复 | 服务端 | 大请求体会被静默截断 | | R-005 | P1 | 已修复 | 服务端 / Qt | CSV/JSON 没有转义会破坏数据和响应 | | R-006 | P1 | 已修复 | STM32 固件 | `sscanf` 未限制宽度,UART 输入可溢出栈缓冲 | | R-007 | P2 | 已修复 | 服务端 | 多个 `std::stoi` 可被非法参数打崩服务线程 | | R-008 | P2 | 已修复 | Qt 管理端 | 删除人脸 URL 未编码 | ## 2. 详细问题 ### R-001 公网接口无鉴权且允许任意来源 - 优先级:P0 - 状态:已修复 - 位置:`server/server_encrypted.cpp:1666` - 影响:服务端暴露清空记录、删除人脸、上传映射、上传照片等写操作,但没有鉴权;响应固定允许任意跨域来源。只要端口可访问,外部请求就可能改写或删除考勤数据。 - 建议处理: 1. 给所有写接口增加 API Token 或签名校验。 2. 按部署环境限制 CORS 来源,不再使用通配符。 3. 公网部署时使用 HTTPS 和反向代理鉴权。 4. 将管理类接口与设备上传接口区分权限。 - 本次处理:主服务端 `server/server_encrypted.cpp` 已增加 `X-Api-Token` 校验,健康检查和 OPTIONS 预检除外;CORS 来源改为 `ATTENDANCE_CORS_ORIGIN` 配置,默认仅本地来源。Qt、STM32、K210 请求均已补 `X-Api-Token`。 ### R-002 明文密钥和凭据已进入项目文件 - 优先级:P0 - 状态:部分修复 - 位置:`k210/main.py:34`、`User/main.c:23`、`QT/qml/Main.qml:2725`、`server/attendance.log` - 影响:项目文件中包含 WiFi 密码、公网服务地址、固定 AES Key/IV、查看账号密码、日志中的疑似 API Key 等敏感信息。泄露后即使代码修复,旧凭据仍可能被继续使用。 - 建议处理: 1. 立即轮换已暴露的 WiFi 密码、API Key、演示账号密码和 AES Key/IV。 2. 将服务地址、WiFi、Token 等改为外部配置文件或烧录参数。 3. 日志输出中屏蔽敏感请求头。 4. 清理已有日志文件中的敏感内容。 - 本次处理:主链路代码和文档中的 WiFi 密码、公网地址改为占位配置;日志中的疑似 API Key 已脱敏;Qt 默认服务地址改为本机地址。仍需在真实环境中轮换已暴露的 WiFi、API Key、演示账号和 AES Key/IV。 ### R-003 `face_id` 可造成路径穿越写读删文件 - 优先级:P1 - 状态:已修复 - 位置:`server/server_encrypted.cpp:837` - 影响:`face_id` 直接来自 URL 并拼接成 `faces/.jpg`,用于写入、读取和删除。包含路径分隔符或 `..` 时,可能越过 `faces` 目录操作其他文件。 - 建议处理: 1. 增加 `face_id` 白名单校验,只允许数字、字母、下划线、短横线等明确字符。 2. 对最终路径做规范化检查,确认仍位于 `faces` 目录下。 3. 所有照片读写删入口共用同一个安全路径构造函数。 - 本次处理:主服务端已增加 `isSafeId` 与 `buildFacePhotoPath`,照片读写删和重命名路径统一走安全 ID 校验。 ### R-004 大请求体会被静默截断 - 优先级:P1 - 状态:已修复 - 位置:`server/server_encrypted.cpp:1228` - 影响:读取 POST body 时,如果剩余数据超过约 40KB,循环不会继续读取,导致照片或配置内容被截断。K210 JPEG 上传很容易触发该问题。 - 建议处理: 1. 按 `Content-Length` 循环读取完整 body。 2. 设置明确最大请求大小,例如照片接口单独允许更大上限。 3. 超限时返回 HTTP 413。 4. 对读取不足的请求返回 400,不保存半截文件。 - 本次处理:主服务端按 `Content-Length` 读取完整请求体,普通 JSON 请求限制 64KB,照片请求限制 512KB,超限返回 413,读取不足返回 400。 ### R-005 CSV/JSON 没有转义会破坏数据和响应 - 优先级:P1 - 状态:已修复 - 位置:`server/server_encrypted.cpp:459`、`QT/src/AppController.cpp:284`、`QT/src/AppController.cpp:317` - 影响:签到记录直接用逗号拼 CSV,读取时也直接按逗号拆,再手写 JSON 字符串。姓名、状态、班级等字段包含逗号、引号、换行或反斜杠时,会导致 CSV 列错位、JSON 非法或 Qt 解析失败。 - 建议处理: 1. 服务端增加 CSV 字段转义和解析函数。 2. 服务端 JSON 响应统一经过 JSON 转义函数。 3. Qt 导出 CSV 时对每个字段做标准 CSV 转义。 4. 使用 SQLite 替代 CSV/多 JSON 文件,减少数据状态不一致。 - 本次处理:主服务端增加 CSV 解析/转义和 JSON 转义;Qt 导出 CSV 已对字段做标准转义;后端主存储已迁移到 `attendance.db`,旧 CSV/JSON 仅作为首次导入来源。 ### R-006 `sscanf` 未限制宽度,UART 输入可溢出栈缓冲 - 优先级:P1 - 状态:已修复 - 位置:`Hardware/K210_USART.c:80` - 影响:`%[^,]` 没有宽度限制,但目标缓冲只有 `id[20]` 和 `name[32]`。串口收到异常长字段时可能覆盖栈内存,造成固件异常。 - 建议处理: 1. 将格式改为 `%19[^,]`、`%31[^,]`。 2. 对接收缓冲做最大帧长、换行结束符和字段合法性校验。 3. 异常帧直接丢弃并清空缓冲。 - 本次处理:`Hardware/K210_USART.c` 和示例文件中的 `sscanf` 已增加字段宽度限制。 ### R-007 多个 `std::stoi` 可被非法参数打崩服务线程 - 优先级:P2 - 状态:已修复 - 位置:`server/server_encrypted.cpp:1310` - 影响:`limit`、`offset`、时间段参数直接调用 `std::stoi`,没有异常捕获和范围校验。非法请求参数可能让请求处理线程异常终止。 - 建议处理: 1. 增加安全整数解析函数。 2. 参数非法时返回 400。 3. 限制 `limit`、`offset` 和时间范围。 4. 所有 URL 参数统一走校验函数。 - 本次处理:主服务端已增加安全整数和时间解析,`limit`、`offset`、时间段和记录时间解析不再直接裸用 `std::stoi`。 ### R-008 删除人脸 URL 未编码 - 优先级:P2 - 状态:已修复 - 位置:`QT/src/ApiClient.cpp:453` - 影响:Qt 端删除人脸时直接把 `studentId` 拼进路径。如果学号包含空格、`#`、`?`、`/` 或中文,URL 会被截断或路由错乱。 - 建议处理: 1. 使用 `QUrl::toPercentEncoding` 编码路径段。 2. 服务端接收后进行 URL 解码和 ID 校验。 3. 为删除人脸接口补充异常 ID 的测试用例。 - 本次处理:Qt 删除人脸路径段已使用 `QUrl::toPercentEncoding` 编码。 ## 3. 建议修复顺序 1. 处理 R-002:轮换凭据,清理敏感日志,避免继续泄露。 2. 处理 R-001:服务端写接口增加鉴权,限制跨域来源。 3. 处理 R-003、R-004:修复文件路径安全和请求体读取,防止文件被覆盖或照片损坏。 4. 处理 R-006:修复固件串口解析溢出风险。 5. 处理 R-005:统一 CSV/JSON 转义,避免数据格式破坏。 6. 处理 R-007、R-008:增强参数健壮性和 Qt URL 构造。 ## 4. 验证记录 - `k210/main.py`、`k210/view_attendance.py` 已通过普通 Python 语法检查;MaixPy 运行时仍需上板验证。 - `server/server_encrypted.cpp` 因当前本机缺少 OpenSSL 头文件,未完成语法编译验证。 - 现有 Keil 构建日志显示固件旧构建为 `0 Error(s), 0 Warning(s)`,但尚未在本次审查中重新编译固件。 - 2026-05-01:已完成主链路安全修复;旧版备用服务端与测试脚本已清理,避免误部署非鉴权接口。