docs(security): libhttp 审计补充下游反馈(P2-7 peer IP / P2-8 流式响应 / P3-3 .so 脱节)

This commit is contained in:
qing committed 2026-08-08 06:58:24 +00:00
1 parent 78bf74b067
commit b6a1cadf25
1 file changed
+32 -3
@@ -4,6 +4,8 @@
**审计范围**: `libhttp/inc/us/`、`libhttp/src/`(HttpServer 6 个拆分 TU + HttpClient + 遗留 WebSocketServer/WebSocketClient)
**代码版本**: dev_qing 分支
**补充轮次**: 2026-08-08 — 下游 fsys 审计反馈(见下方“下游审计反馈”节,新增 P2-7/P2-8/P3-3)
---
## 修复进度
@@ -12,8 +14,11 @@
|--------|------|--------|----------|--------|
| P0 | 0 | 0 | 0 | 0 |
| P1 | 6 | 6 | 0 | 0 |
| P2 | 4 | 0 | 0 | 4 |
| **合计** | **10** | **8** | **0** | **2** |
| P2 | 8 | 0 | 0 | 8 |
| P3 | 3 | 2 | 0 | 1 |
| **合计** | **17** | **8** | **0** | **9** |
> 勘误:原汇总表 P2 总数误记为 4(实际 P2 节含 P2-1~P2-6 共 6 项),本次随 2026-08-08 补充一并修正。
---
@@ -34,12 +39,14 @@
| # | 问题 | 状态 | 说明 |
|---|------|------|------|
| P2-1 | CORS 反射任意 Origin | ❌ 未修复 | OPTIONS 预检(`HttpServer_Request.cpp` L73-74)把 `Access-Control-Allow-Origin` 直接设为请求的 `Origin` 值,任意来源均被放行,无白名单校验(对应全局审计 P2-3 根因) |
| P2-1 | CORS 反射任意 Origin | ❌ 未修复 | OPTIONS 预检(`HttpServer_Request.cpp` L73-74)把 `Access-Control-Allow-Origin` 直接设为请求的 `Origin` 值,任意来源均被放行,无白名单校验(对应全局审计 P2-3 根因)。**下游影响已确认**(fsys 审计 D-2):应用未显式注册 OPTIONS 的路由均落入此内置预检,白名单形同虚设;仅因实际应用响应不带 ACAO 头才封住跨域读取 |
| P2-2 | TLS 客户端一律不校验证书 | ❌ 未修复 | `HttpClient.cpp` L131 与 WS 代理 `HttpServer_WsSession.cpp` L243 均 `set_verify_mode(asio::ssl::verify_none)`。对内部后端可接受,但库内不留逃生口,无法在需要校验时启用 |
| P2-3 | WebSocket 握手无 Origin/CSWSH 校验 | ❌ 未修复 | libhttp 对任意 `ws`/`ws_proxy` upgrade 请求直接握手,不校验 `Origin`/`Sec-WebSocket-Protocol`。若后端依赖 Cookie 鉴权,存在跨站 WebSocket 劫持(CSWSH)风险(gateway 的 `ws_proxy` 依赖握手回调鉴权,属应用层缓解) |
| P2-4 | HttpClient `ws_recv` 忽略 timeout 参数 | ❌ 未修复 | `HttpClient.cpp` L220-221 `(void)timeout_ms;` 丢弃超时参数,`ws_recv` 会**无限阻塞**。后端挂起时调用线程永久卡死 |
| P2-5 | 反向代理后端连接建立后无超时 | ❌ 未修复 | 代理后端握手成功后 `proxy_tcp_stream_->expires_never()`(`HttpServer_WsSession.cpp` L262/L287),双向读写无超时,慢后端可长期占用连接 |
| P2-6 | 无连接数限制 | ❌ 未修复 | `Listener::doAccept`(`HttpServer_Listener.cpp` L23-48)无限接受连接,每连接一个 Session,无最大连接数上限,可被连接耗尽 |
| P2-7 | handler 无法获取客户端真实 IP | ❌ 未修复 | handler 签名仅接收 `req + params`,`Session::remote_ip_`/`getRemoteAddress()`(`HttpServerImpl.hpp` L63)不对外暴露。**下游影响**(fsys 审计 L-2):限速/审计日志只能信任 XFF 头,XFF 缺失时回退全局共享键,直连时 XFF 可伪造,限速防护弱化。建议:通过 params 注入或扩展 handler 上下文暴露 peer IP |
| P2-8 | 响应仅支持 string_body,无 file_body/chunked | ❌ 未修复 | `handleRequest`/handler 返回类型固定为 `http::response<http::string_body>`,静态文件服务必须全量读入内存(内置静态分支 `HttpServer_Request.cpp` L95-119 同样如此)。**下游影响**(fsys 审计 L-1/F-4):fsys 只能用 50MB 上限缓解大文件 DoS,无法对齐 Python 版 `send_file` 流式能力。建议:支持 `file_body` 或 chunked 序列化响应 |
---
@@ -49,6 +56,22 @@
|---|------|------|------|
| P3-1 | 遗留 WebSocketServer/WebSocketClient 未构建 | ✅ 已修复 | 已删除 `WebSocketServer.cpp`/`WebSocketClient.cpp`/`WebSocketServer.hpp`/`WebSocketClient.hpp`/`WebSocketClientBase.hpp`(未构建、与 `HttpClient` 别名同名冲突、有缺陷),并清理 Makefile/README 引用。WebSocket 能力由 `HttpServer` + `HttpClient` 提供 |
| P3-2 | CMakeLists.txt 过时 | ✅ 已修复 | CMakeLists 已重写对齐 Makefile:`libus_http.so`(6 个服务端 TU)+ `libus_httpclient.so`(HttpClient),移除遗留文件引用与错误库名 |
| P3-3 | 预编译 .so 与源码脱节(set_timeout 符号缺失) | ❌ 未修复 | dnfs2 审计 P2-N5 已在源码新增 `HttpClient::set_timeout/set_connect_timeout`(`HttpClient.cpp` L45/L53),但 `build/` 目录的预编译产物为旧源码编译,`nm -D libus_httpclient.so` 无对应符号,下游 fsys 调用即链接失败(被迫回退默认 30s 超时)。且 `build/` 属主为 root,普通用户无法重建。建议:以 root 重编译发布与源码一致的 .so,或调整 build 目录权限 |
---
## 下游审计反馈(2026-08-08,fsys 第 1 轮审计)
fsys(static 的 C++ 重写,首个大规模使用 HttpServer + HttpClient 的业务模块)审计中确认/新发现以下 libhttp 侧问题,均已录入上方表格:
| 编号 | 反馈 | fsys 侧缓解 |
|------|------|-------------|
| P2-1 | 内置 OPTIONS 反射任意 Origin,下游未注册 OPTIONS 的路由白名单失效 | 应用响应不带 ACAO,跨域读取被浏览器拦截(影响有限但非根治) |
| P2-7 | handler 无 peer IP,限速只能信 XFF | XFF 缺失回退 "unknown" 全局键 + 键数上限 65536 驱逐 |
| P2-8 | 无流式响应,大文件全量读入内存 | 50MB 上限(413/416),残留限制记 fsys L-1 |
| P3-3 | 预编译 .so 缺 set_timeout 符号 | 移除调用,使用默认 30s 超时 |
交叉引用: `docs/security/fsys_SECURITY_AUDIT_20260808.md`(D-2/L-1/L-2 节)
---
@@ -83,6 +106,9 @@
- [ ] P2-5 代理后端读写超时 + 空闲保活
- [ ] P2-6 最大连接数限制
- [ ] P2-2 TLS 校验可配置(至少提供 `verify_peer` 选项)
- [ ] P2-7 handler 暴露 peer IP(params 注入或 handler 上下文扩展)——下游限速/审计依赖
- [ ] P2-8 支持 file_body/chunked 响应——下游静态服务流式传输依赖
- [ ] P3-3 重编译发布与源码一致的 .so(补 set_timeout 符号),解决 build/ 目录 root 权限问题
- [x] P3-1 删除或维护遗留 WebSocketServer/WebSocketClient → ✅ 已删除
- [x] P3-2 同步 CMakeLists.txt 与 Makefile → ✅ 已重写对齐
@@ -107,4 +133,7 @@
| HttpClient 响应无上限 | `src/HttpClient.cpp` | L63-81, L329-334 |
| HttpClient TLS verify_none | `src/HttpClient.cpp` | L131 |
| HttpClient ws_recv 忽略超时 | `src/HttpClient.cpp` | L220-221 |
| HttpClient set_timeout(源码已有,.so 缺符号) | `src/HttpClient.cpp` / `inc/us/HttpClient.hpp` | L45, L53 / L70, L73 |
| Session peer IP(未暴露给 handler) | `inc/us/detail/HttpServerImpl.hpp` | L63, L122 |
| 内置静态文件(string_body 全量读) | `src/HttpServer_Request.cpp` | L95-119 |
| ~~遗留 WS 实现(已删除)~~ | ~~`src/WebSocketServer.cpp`、`src/WebSocketClient.cpp`~~ | 已删除(见 P3-1),WebSocket 能力由 `HttpServer` + `HttpClient` 提供 |