[H-01][medium] 管理接口请求体大小与读取时间不受限制,公开的登录接口可被打爆内存 #44

Closed
opened 2026-09-30 13:57:01 +08:00 by nixevol · 1 comment
Owner

编号:H-01 严重级:medium 工作线:管理后端(internal/admin) 来源:审查 A-13、P-17
依赖:无 被依赖:无

结论与统一方案

两份审查结论一致:后台默认与端共用公网端口,/api/admin/login 无需登录即可访问,而 httpx.DecodeJSON 不限大小,http.Server 只设了 ReadHeaderTimeout。统一方案:

  1. httpx.DecodeJSON 内部改用 http.MaxBytesReader(nil, r.Body, 1<<20),函数签名不变,覆盖所有 JSON 接口。(审查 P-17)
  2. admin.Handler.ServeHTTP 按路由设置请求体上限(登录可以更小,导入 8 MiB)与读取截止时间(http.NewResponseController(w).SetReadDeadline),超限返回 413 JSON;CSV 导入超过 8 MiB 返回 413,不再静默截断。(审查 A-13)
  3. 不在 listener 上加全局 ReadTimeout,会误伤劫持后的 WebSocket(见 L-01)。

改动文件

internal/httpx/json.go、internal/admin/handler.go、endpoints_csv.go。

与其他问题的交互 / 冲突说明

  • json.go 只有本条修改。
  • handler.go 与 H-02(审计 logger 注入)相邻,endpoints_csv.go 与 H-04 相邻,管理后端线内顺序合入。

验收与测试

  • 1 MiB 以上的登录请求体很快返回 413;超过 8 MiB 的 CSV 返回 413。
  • 用 2 MiB 的请求体调 DecodeJSON 返回错误。

问题明细(各区审查原文,证据含文件与行号)

以下是本次复审各区审查报告的原文段落。A、M、I、P、S 开头的是原始发现编号(A 管理后台与网页、M 消息核心、I 身份认证群在线、P 传输平台部署、S SDK)。解决方案以本 issue 上方的"结论与统一方案"为准;原文里的方案与之不一致时,按上方执行。

[A-13] 管理接口请求体大小和读取时间不受限制,公开的登录接口可被打爆内存

  • 严重级:medium
  • 分类:安全
  • 现象与影响:
    • 默认后台和端共用公网端口,/api/admin/login 不需要登录。DecodeJSON 不限大小,传一个 GB 级的 JSON 字符串就能耗尽内存。
    • http.Server 只设了 ReadHeaderTimeout,慢速发送请求体可以长期占住连接。
    • 对比之下,注册接口把请求体限制在 4 KiB。
    • CSV 导入用 LimitReader 在 8 MiB 处静默截断,而不是报错。
  • 证据:
    • internal/httpx/json.go:49-61。
    • login.go:33-40。
    • listener/server.go:122-125,156-159。
    • identity/register.go:23(4 KiB)。
    • endpoints_csv.go:94,106。
  • 文档依据:PRD §8 安全"管理员登录……防暴力尝试";DEVELOPMENT 4.1 默认共用端口。
  • 为何不是故意设计:DEVIATIONS 没有相关条目。
  • 解决方案:在 admin.Handler.ServeHTTP 统一处理:
    1. r.Body = http.MaxBytesReader(w, r.Body, n),导入 8 MiB,其余 64 KiB,登录可以更小。
    2. 用 http.NewResponseController(w).SetReadDeadline(...) 限制读请求体的时间,导入可以放宽。
    3. 超限返回 413,JSON 格式。
    4. 不要在 listener 上加全局 ReadTimeout,会误伤劫持后的 WebSocket。
  • 改动文件:internal/admin/handler.go、internal/admin/endpoints_csv.go。
  • 交互/冲突风险:只影响管理路由。
  • 需补测试:1 MiB 的登录请求体很快返回 413;超过 8 MiB 的 CSV 返回 413。
  • 置信度:代码阅读确定

[P-17] httpx.DecodeJSON 不限制请求体大小

  • 严重级:medium
  • 分类:安全
  • 现象与影响:
    • DecodeJSON 直接读整个请求体。后台默认和端共用公网端口,而 /api/admin/login 不需要登录就能访问。
    • 发一个几百 MB 的 password 字段会被完整读进内存,argon2 还会对超长口令整段计算。
    • 没有 ReadTimeout,还可以慢速上传长期占着连接。注册接口自己加了 MaxBytesReader,后台的 JSON 接口都没有。
  • 证据:httpx/json.go:49-61;admin/login.go:33-40;identity/register.go:104。
  • 文档依据:PRD 第 8 节安全(管理员登录防暴力)。
  • 为何不是故意设计:没有记录。
  • 解决方案:DecodeJSON 内部改用 http.MaxBytesReader(nil, r.Body, 1<<20),函数签名不变。批量开通 1000 行的 JSON 约 200 KiB,1 MiB 留足了余量;CSV 导入有自己单独的读取逻辑,不受影响。
  • 改动文件:internal/httpx/json.go
  • 与其他模块的交互/冲突风险:A 线的管理接口不用改调用点。
  • 需补测试:用 2 MiB 的请求体调 DecodeJSON,返回错误。
  • 置信度:代码阅读确定

复审基线:main 4059a15(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。

**编号**:H-01 **严重级**:medium **工作线**:管理后端(internal/admin) **来源**:审查 A-13、P-17 **依赖**:无 **被依赖**:无 ### 结论与统一方案 两份审查结论一致:后台默认与端共用公网端口,`/api/admin/login` 无需登录即可访问,而 `httpx.DecodeJSON` 不限大小,`http.Server` 只设了 `ReadHeaderTimeout`。统一方案: 1. `httpx.DecodeJSON` 内部改用 `http.MaxBytesReader(nil, r.Body, 1<<20)`,函数签名不变,覆盖所有 JSON 接口。(审查 P-17) 2. `admin.Handler.ServeHTTP` 按路由设置请求体上限(登录可以更小,导入 8 MiB)与读取截止时间(`http.NewResponseController(w).SetReadDeadline`),超限返回 413 JSON;CSV 导入超过 8 MiB 返回 413,不再静默截断。(审查 A-13) 3. 不在 listener 上加全局 `ReadTimeout`,会误伤劫持后的 WebSocket(见 L-01)。 ### 改动文件 `internal/httpx/json.go`、`internal/admin/handler.go`、`endpoints_csv.go`。 ### 与其他问题的交互 / 冲突说明 - `json.go` 只有本条修改。 - `handler.go` 与 H-02(审计 logger 注入)相邻,`endpoints_csv.go` 与 H-04 相邻,管理后端线内顺序合入。 ### 验收与测试 - 1 MiB 以上的登录请求体很快返回 413;超过 8 MiB 的 CSV 返回 413。 - 用 2 MiB 的请求体调 `DecodeJSON` 返回错误。 --- ### 问题明细(各区审查原文,证据含文件与行号) > 以下是本次复审各区审查报告的原文段落。A、M、I、P、S 开头的是原始发现编号(A 管理后台与网页、M 消息核心、I 身份认证群在线、P 传输平台部署、S SDK)。**解决方案以本 issue 上方的"结论与统一方案"为准**;原文里的方案与之不一致时,按上方执行。 #### [A-13] 管理接口请求体大小和读取时间不受限制,公开的登录接口可被打爆内存 - 严重级:medium - 分类:安全 - 现象与影响: - 默认后台和端共用公网端口,`/api/admin/login` 不需要登录。`DecodeJSON` 不限大小,传一个 GB 级的 JSON 字符串就能耗尽内存。 - `http.Server` 只设了 `ReadHeaderTimeout`,慢速发送请求体可以长期占住连接。 - 对比之下,注册接口把请求体限制在 4 KiB。 - CSV 导入用 `LimitReader` 在 8 MiB 处静默截断,而不是报错。 - 证据: - `internal/httpx/json.go:49-61`。 - `login.go:33-40`。 - `listener/server.go:122-125,156-159`。 - `identity/register.go:23`(4 KiB)。 - `endpoints_csv.go:94,106`。 - 文档依据:PRD §8 安全"管理员登录……防暴力尝试";DEVELOPMENT 4.1 默认共用端口。 - 为何不是故意设计:DEVIATIONS 没有相关条目。 - 解决方案:在 `admin.Handler.ServeHTTP` 统一处理: 1. `r.Body = http.MaxBytesReader(w, r.Body, n)`,导入 8 MiB,其余 64 KiB,登录可以更小。 2. 用 `http.NewResponseController(w).SetReadDeadline(...)` 限制读请求体的时间,导入可以放宽。 3. 超限返回 413,JSON 格式。 4. 不要在 listener 上加全局 `ReadTimeout`,会误伤劫持后的 WebSocket。 - 改动文件:`internal/admin/handler.go`、`internal/admin/endpoints_csv.go`。 - 交互/冲突风险:只影响管理路由。 - 需补测试:1 MiB 的登录请求体很快返回 413;超过 8 MiB 的 CSV 返回 413。 - 置信度:代码阅读确定 #### [P-17] httpx.DecodeJSON 不限制请求体大小 - **严重级**:medium - **分类**:安全 - **现象与影响**: - `DecodeJSON` 直接读整个请求体。后台默认和端共用公网端口,而 `/api/admin/login` 不需要登录就能访问。 - 发一个几百 MB 的 password 字段会被完整读进内存,argon2 还会对超长口令整段计算。 - 没有 `ReadTimeout`,还可以慢速上传长期占着连接。注册接口自己加了 `MaxBytesReader`,后台的 JSON 接口都没有。 - **证据**:`httpx/json.go:49-61`;`admin/login.go:33-40`;`identity/register.go:104`。 - **文档依据**:PRD 第 8 节安全(管理员登录防暴力)。 - **为何不是故意设计**:没有记录。 - **解决方案**:`DecodeJSON` 内部改用 `http.MaxBytesReader(nil, r.Body, 1<<20)`,函数签名不变。批量开通 1000 行的 JSON 约 200 KiB,1 MiB 留足了余量;CSV 导入有自己单独的读取逻辑,不受影响。 - **改动文件**:`internal/httpx/json.go` - **与其他模块的交互/冲突风险**:A 线的管理接口不用改调用点。 - **需补测试**:用 2 MiB 的请求体调 `DecodeJSON`,返回错误。 - **置信度**:代码阅读确定 --- <sub>复审基线:main `4059a15`(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。</sub>
nixevol added the P2-mediumlane/adminreview-2026-09-30 labels 2026-09-30 13:57:01 +08:00
Author
Owner

已合入 origin/main 0c9b459。落地提交 1a4bf6f fix: 限制管理接口请求体大小与读取时间 (#44)。

已合入 origin/main `0c9b459`。落地提交 `1a4bf6f` fix: 限制管理接口请求体大小与读取时间 (#44)。
Sign in to join this conversation.