8.1 KiB
8.1 KiB
项目审查问题清单
审查日期: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 - 影响:服务端暴露清空记录、删除人脸、上传映射、上传照片等写操作,但没有鉴权;响应固定允许任意跨域来源。只要端口可访问,外部请求就可能改写或删除考勤数据。
- 建议处理:
- 给所有写接口增加 API Token 或签名校验。
- 按部署环境限制 CORS 来源,不再使用通配符。
- 公网部署时使用 HTTPS 和反向代理鉴权。
- 将管理类接口与设备上传接口区分权限。
- 本次处理:主服务端
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 等敏感信息。泄露后即使代码修复,旧凭据仍可能被继续使用。
- 建议处理:
- 立即轮换已暴露的 WiFi 密码、API Key、演示账号密码和 AES Key/IV。
- 将服务地址、WiFi、Token 等改为外部配置文件或烧录参数。
- 日志输出中屏蔽敏感请求头。
- 清理已有日志文件中的敏感内容。
- 本次处理:主链路代码和文档中的 WiFi 密码、公网地址改为占位配置;日志中的疑似 API Key 已脱敏;Qt 默认服务地址改为本机地址。仍需在真实环境中轮换已暴露的 WiFi、API Key、演示账号和 AES Key/IV。
R-003 face_id 可造成路径穿越写读删文件
- 优先级:P1
- 状态:已修复
- 位置:
server/server_encrypted.cpp:837 - 影响:
face_id直接来自 URL 并拼接成faces/<face_id>.jpg,用于写入、读取和删除。包含路径分隔符或..时,可能越过faces目录操作其他文件。 - 建议处理:
- 增加
face_id白名单校验,只允许数字、字母、下划线、短横线等明确字符。 - 对最终路径做规范化检查,确认仍位于
faces目录下。 - 所有照片读写删入口共用同一个安全路径构造函数。
- 增加
- 本次处理:主服务端已增加
isSafeId与buildFacePhotoPath,照片读写删和重命名路径统一走安全 ID 校验。
R-004 大请求体会被静默截断
- 优先级:P1
- 状态:已修复
- 位置:
server/server_encrypted.cpp:1228 - 影响:读取 POST body 时,如果剩余数据超过约 40KB,循环不会继续读取,导致照片或配置内容被截断。K210 JPEG 上传很容易触发该问题。
- 建议处理:
- 按
Content-Length循环读取完整 body。 - 设置明确最大请求大小,例如照片接口单独允许更大上限。
- 超限时返回 HTTP 413。
- 对读取不足的请求返回 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 解析失败。
- 建议处理:
- 服务端增加 CSV 字段转义和解析函数。
- 服务端 JSON 响应统一经过 JSON 转义函数。
- Qt 导出 CSV 时对每个字段做标准 CSV 转义。
- 使用 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]。串口收到异常长字段时可能覆盖栈内存,造成固件异常。 - 建议处理:
- 将格式改为
%19[^,]、%31[^,]。 - 对接收缓冲做最大帧长、换行结束符和字段合法性校验。
- 异常帧直接丢弃并清空缓冲。
- 将格式改为
- 本次处理:
Hardware/K210_USART.c和示例文件中的sscanf已增加字段宽度限制。
R-007 多个 std::stoi 可被非法参数打崩服务线程
- 优先级:P2
- 状态:已修复
- 位置:
server/server_encrypted.cpp:1310 - 影响:
limit、offset、时间段参数直接调用std::stoi,没有异常捕获和范围校验。非法请求参数可能让请求处理线程异常终止。 - 建议处理:
- 增加安全整数解析函数。
- 参数非法时返回 400。
- 限制
limit、offset和时间范围。 - 所有 URL 参数统一走校验函数。
- 本次处理:主服务端已增加安全整数和时间解析,
limit、offset、时间段和记录时间解析不再直接裸用std::stoi。
R-008 删除人脸 URL 未编码
- 优先级:P2
- 状态:已修复
- 位置:
QT/src/ApiClient.cpp:453 - 影响:Qt 端删除人脸时直接把
studentId拼进路径。如果学号包含空格、#、?、/或中文,URL 会被截断或路由错乱。 - 建议处理:
- 使用
QUrl::toPercentEncoding编码路径段。 - 服务端接收后进行 URL 解码和 ID 校验。
- 为删除人脸接口补充异常 ID 的测试用例。
- 使用
- 本次处理:Qt 删除人脸路径段已使用
QUrl::toPercentEncoding编码。
3. 建议修复顺序
- 处理 R-002:轮换凭据,清理敏感日志,避免继续泄露。
- 处理 R-001:服务端写接口增加鉴权,限制跨域来源。
- 处理 R-003、R-004:修复文件路径安全和请求体读取,防止文件被覆盖或照片损坏。
- 处理 R-006:修复固件串口解析溢出风险。
- 处理 R-005:统一 CSV/JSON 转义,避免数据格式破坏。
- 处理 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:已完成主链路安全修复;旧版备用服务端与测试脚本已清理,避免误部署非鉴权接口。