综合 Nginx UI 六个 CVE 复盘:AuthRequired 只校验 JWT,不校验会话,v2.5.0 才补上 RequireSecureSession

2026-10-23 21:02:14

Nginx UI 六个 CVE 复盘:AuthRequired 只校验 JWT,不校验会话,v2.5.0 才补上 RequireSecureSession

事件概览

2026 年 10 月 9 日,Nginx UI 发布 v2.5.0,一次性修复六个高危 CVE,全部同日披露,影响范围统一为 2.0.0 – 2.4.x。单个维护者维护的单套代码库,暴露出六条相互独立的认证、鉴权与配置完整性破坏路径:其中五条属于认证与鉴权缺陷,一条属于供应链缺陷。

CVE问题类型
CVE-2026-107808仅启用 passkey 的账号在只提供密码的情况下也被签发会话认证绕过
CVE-2026-107809AuthRequired 接受 JWT cookie 而不校验 CSRF tokenCSRF
CVE-2026-107810备份恢复时解压指向线上配置的 symlink配置注入
CVE-2026-107811/api/nodes 泄露的节点 token 可被 AuthRequired 接受跨节点认证绕过
CVE-2026-107813集群接口只挂 AuthRequired、未挂 RequireSecureSession失效 JWT 提权
CVE-2026-107812升级包 digest 仅与同源镜像比对镜像失陷 → RCE

根因:网关只校验 token,不校验 token 的来源

所有与认证相关的 CVE 都指向同一个假设:只要用户持有 JWT,就认为其已通过认证。

AuthRequired 会校验 JWT,也会校验 OTP,但它不会调用 RequireSecureSession;而后者本应确认该会话是否通过了第二因子验证。由此带来以下后果:

  • 添加 passkey 之前窃取的 JWT 可以一直使用,不会失效(107813)
  • 启用了 passkey 的账号仅凭密码即可获得会话,不经过 passkey 校验(107808)
  • JWT cookie 在没有 CSRF 保护的情况下跨源可用(107809)
  • /api/nodes 返回的节点 token 经 AuthRequired 直接映射为 initUser(107811)

问题不在于每个端点都忘了单独加固;真正的问题在于这层网关本身设计有缺陷:它只确认请求携带了 token,却不确认 token 是如何获得的。所有挂在这层网关之后的端点都继承同一个弱点。

两条非认证链路

CVE-2026-107810(备份 symlink 注入) 是否属于认证问题?不是,但它同属一种设计取向:信任已认证用户的选择。恢复逻辑在执行 flag 之前先解包内层归档,并且允许归档中包含 symlink。链路是:构造备份 → 建立 symlink 暂存目录树 → 通过链接写入普通文件 → 持久化配置注入。即使 restore_nginx 和 restore_nginx_ui 两个 flag 都为 false,这条链路依然成立。

CVE-2026-107812(升级包 digest 校验) 属于同一类问题的另一条链路:信任同源镜像、校验 digest、安装。当镜像失陷或网络攻击者同时篡改二进制文件和 digest 时,恶意程序最终会在 Nginx UI 的进程上下文中运行。

v2.5.0 的修复

修复的是架构层面的问题,并不停留在表面修补:

  • AuthRequired 在管理端点上调用 RequireSecureSession,对启用 OTP 的账号校验第二因子 step-up
  • 备份恢复逻辑校验 symlink 目标必须位于解压目录内
  • 升级包 digest 校验改用签名 manifest,不再仅依赖同源
  • 节点 token 被限定在其来源节点范围内使用

运维检查清单

1. 确认版本

遍历所有实例(含边缘节点、容器镜像 tag、离线包),凡是落在 2.0.0 – 2.4.x 的,一律升级到 v2.5.0。不要只查入口那一台机器,节点侧经常是漏掉的。

2. 验证 passkey-only 账号是否会被密码登录绕过

找一个仅启用 passkey 的测试账号(或临时账号),关掉 WebAuthn 交互,只用密码走一次登录。如果拿到会话,说明 107808 在该实例上可被利用。检查生产账号中是否存在“已启用 passkey、但仍保留密码登录路径”的组合,这类账号在本漏洞下等同于仅使用密码。

3. 让存量 JWT 失效

107813 的核心是旧 JWT 不因新增 passkey 而失效。升级后应强制所有用户重新登录,并重点复核集群管理账号的会话是否仍有长时间未重新认证的残留。对启用了 OTP 的账号,确认管理操作确实触发了 step-up,而不仅是首页可访问。

4. 轮换 node secret 并重新配对节点

107811 的细节是:cluster 初始化路由挂在共享的已认证 API 路由组内,任意已认证用户都能访问 /api/nodes 与 /api/nodes/:id;节点对象的 token 字段序列化时没有脱敏(json:"token")。节点间认证中间件接受 X-Node-Secret 请求头或 node_secret 查询参数中的节点密钥,一旦与系统 node secret 设置匹配,请求就会被关联到 initUser,绕过标准用户认证。因此升级后应在设置里重置 node secret,逐个重新配对节点,并检查访问日志中是否出现过 node_secret= 形式的查询串——查询参数会进入日志、代理与浏览器历史。

5. 限制管理口暴露面

集群路由包含节点与 namespace 的变更操作,以及集群级 Nginx 重载与重启端点(nodes/reload_nginx、nodes/restart_nginx)。这些端点不应暴露在公网:管理端口只允许内网或跳板机访问,前面加一层独立的反向代理认证,并确保 /api/nodes 不被外部路由规则意外放行。

6. 审计备份恢复记录

检查历史备份恢复操作中,归档内是否包含 symlink 条目,以及是否有异常的文件写入落到 Nginx 配置目录。107810 在恢复 flag 关闭时仍可能生效,因此“没开恢复选项”不能作为排除依据。

两条公告的补充细节

CVE-2026-107813 的公告说明:api/cluster 路由暴露节点与 namespace 的变更操作,以及集群级 Nginx reload / restart 端点(nodes/reload_nginx、nodes/restart_nginx),这些端点只挂了 AuthRequired,没有挂 RequireSecureSession。受影响版本为 2.0.0 – 2.4.x,修复于 2.5.0,GitHub Security Advisory 编号 GHSA-h246-wpgf-vmq5。

CVE-2026-107811 的 CVSS 为 8.8,修复于 2.5.0,对应 commit 0ecbd106c37b。

项目信息

  • 项目地址:
  • 修复版本:v2.5.0
复制全文 生成海报 Nginx 安全 运维 鉴权

推荐文章

程序员茄子在线接单