我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 97.1% 的成绩。 了解更多

深度解析

深度解析

Xen Orchestra 认证绕过被利用以接管主机(VSA-2026-062)

authenticationToken Cookie 中的空 JSON 对象可绕过 Xen Orchestra 认证并获得管理员权限;攻击者正在利用,6.9.2 已修复。

TL;DR

  • authenticationToken Cookie 中的空 JSON 对象会让 Xen Orchestra 把请求当作已认证管理员的请求。令牌查询收到该对象后,将其视为无过滤条件的查询,并返回存储的第一个令牌。
  • 稳定通道 6.9.2 之前、最新通道 6.10.1 之前的 Xen Orchestra 受影响,包括 Xen Orchestra Appliance。xo-server 软件包为 5.211.2 和 5.213.1。
  • 供应商将该缺陷评为严重,并表示正在被实际利用。截至 2026 年 11 月 11 日,尚未分配 CVE,也未列入 CISA 的 Known Exploited Vulnerabilities 目录。
  • 更新到 6.9.2 或 6.10.1,或更新 xo-server 到 5.211.2 或 5.213.1。如果无法更新,请在代理处阻止空令牌 Cookie,并将实例从互联网移除。

我受影响吗?

必须同时满足以下条件:

  • 在稳定通道运行 6.9.2 之前的 Xen Orchestra,或在最新通道运行 6.10.1 之前的版本。Xen Orchestra Appliance 也受影响。
  • 攻击者可以访问 REST API。易受攻击的路径是读取 authenticationToken Cookie 的 REST 认证中间件。
  • 实例的令牌集合中至少有一个未过期的认证令牌。用户在登录并选择保持登录状态时会创建令牌,因此大多数活跃部署都有。

供应商表示缺陷位于 Xen Orchestra,而不是 XCP-ng。由于 Xen Orchestra 持有受管池的管理员凭据,影响会波及这些池。被入侵的控制台可以在其管理的每台主机上执行命令。

Xen Orchestra 是 XCP-ng(XenServer 的开源替代品)的管理控制台。项目仓库在 GitHub 上有 998 个星标,社区容器镜像 ronivay/xen-orchestra 在 Docker Hub 上有 2,777,836 次拉取,这反映了运行该控制台的部署规模。

通道 受影响版本 修复版本
稳定 6.9.2 之前的 Xen Orchestra、5.211.2 之前的 xo-server Xen Orchestra 6.9.2、xo-server 5.211.2
最新 6.10.1 之前的 Xen Orchestra、5.213.1 之前的 xo-server Xen Orchestra 6.10.1、xo-server 5.213.1

检查 xo-server 软件包版本。从源码安装时,在仓库根目录运行:

node -p "require('./packages/xo-server/package.json').version"
npm ls xo-server -g --depth=0

在 Xen Orchestra Appliance 上,打开 Web 界面的 About 页面并查看 Xen Orchestra 版本。供应商也在公告中公布了修复后的 xo-server 版本。如果版本是 5.211.2 或 5.213.1,则实例已修复;更早的版本号受影响。

如何修复?

将 Xen Orchestra 更新到稳定通道的 6.9.2 或最新通道的 6.10.1,然后重启服务。从源码安装的实例应更新到最新 master 并重新构建。

  1. 在稳定通道,更新到 Xen Orchestra 6.9.2,其中包含 xo-server 5.211.2。
  2. 在最新通道,更新到 Xen Orchestra 6.10.1,其中包含 xo-server 5.213.1。
  3. 从源码安装时,拉取最新 master,执行常规安装和构建步骤,然后重启 xo-server。
  4. 使用“我受影响吗?”中的命令确认新的 xo-server 版本。
  5. 如果使用 Appliance,请应用供应商更新并确认 About 页面显示 6.9.2 或 6.10.1。

如果无法更新,请将实例从互联网移除,并在代理处阻止空令牌。供应商列出三项缓解措施:

  1. 将 Xen Orchestra 放在专用管理网络中,不要暴露到互联网。
  2. 阻止供应商与该活动关联的 IP 地址和 Tor 域名。列表见“如何检查是否已遭入侵?”。
  3. 添加 WAF 或反向代理规则,拒绝 authenticationToken=j:{} 和 authenticationToken=j:%7B%7D。供应商警告正则规则可能被其他编码绕过,因此请将其视为临时措施。

如果发现任何入侵迹象,请轮换控制台可访问的所有凭据。包括池密钥、主机 root 密码、用户账户、OTP 密钥、备份目标凭据和邮件服务器密码。供应商建议在确认入侵后进行完整重装,因为仅靠清理无法保证后门已消失。

根本原因是什么?

REST API 使用 cookie-parser 中间件解析 Cookie,该中间件将 j: 前缀理解为 JSON。authenticationToken=j:%7B%7D 的 Cookie 值会被解码为空对象 {}。随后 REST 中间件将该对象作为令牌传给认证提供程序:

  async #authenticateUser(req) {
    const { cookies, ip } = req
    const token = cookies.authenticationToken ?? cookies.token

    if (!token) {
      throw invalidCredentials()
    }

    const { user } = await this.#app.authenticateUser({ token }, { ip })

提供程序只检查值是否为真。空对象为真,因此请求继续:

    this.registerAuthenticationProvider(async ({ token: tokenId }, { ip } = {}) => {
      if (!tokenId) {
        return
      }

      try {
        const token = await app.getAuthenticationToken(tokenId)

getAuthenticationToken 期望字符串或带 id 字段的对象。它读取 properties.id 而不检查类型,因此空对象产生 undefined:

  async getAuthenticationToken(properties) {
    const id = typeof properties === 'string' ? properties : properties.id

    const token = await this._getAuthenticationToken(id, properties)

_getAuthenticationToken 在对象存在时将其传给令牌集合:

  async _getAuthenticationToken(id, properties) {
    const token = await this._tokens.first(properties ?? id)

集合的 first({}) 将空对象视为无条件查询,并返回其持有的第一个令牌。如果该令牌未过期,提供程序会将请求认证为该令牌的所有者。攻击者无需知道任何凭据;对象本身就会选中记录。

如何被利用?

  1. 攻击者向 Xen Orchestra REST API 发送 HTTP 请求,携带 Cookie authenticationToken=j:%7B%7D(或 authenticationToken=j:{})。
  2. cookie-parser 将 j: 值解码为空对象 {}。
  3. REST 中间件将 { token: {} } 传给认证提供程序。提供程序的真值检查接受该对象。
  4. getAuthenticationToken 读取 properties.id,其为 undefined,并将原对象转发给令牌集合。
  5. 集合的 first({}) 返回第一个令牌。提供程序检查其过期时间,并将请求认证为该令牌的所有者。
  6. 攻击者使用获得的会话调用 /rest/v0/users/me/authentication_tokens,收到可复用的登录令牌 ID。
  7. 攻击者使用管理员会话更改配置、在受管池上执行命令,并以 root 身份访问 XCP-ng 主机。

供应商表示该利用可导致受管池上的任意代码执行,以及以 root 身份完全接管 XCP-ng 节点。除 Cookie 模式外,供应商未公布确切的请求序列,下面的指标属于该活动,而非完整的检测方法。

攻击如何展开?

一个空 JSON 对象替换了令牌标识符,令牌集合返回第一条记录,请求变成可访问受管主机的管理员会话。

flowchart LR A["攻击者发送 authenticationToken=j:%7B%7D"] --> B["cookie-parser 将 j: 转为 {}"] B --> C["REST 中间件传递 { token: {} }"] C --> D["提供程序接受真值对象
无字符串检查"] D --> E["集合 first({})
返回第一个令牌"] E --> F["以令牌所有者身份建立会话
通常是管理员"] F --> G["在受管池和
XCP-ng 主机上执行命令"]

攻击者能做什么?

到达 REST API 的攻击者可以认证为第一个未过期令牌的所有者。实际上通常是管理员,因为该会话随后可以调用仅限管理员的 REST 路由。

影响包括:

  • 读取和更改 Xen Orchestra 配置、用户和认证令牌。
  • 通过 Xen Orchestra 的主机访问在受管池上执行命令。
  • 如供应商所述,以 root 身份接管 XCP-ng 节点。
  • 收集代理、备份目标(NFS、S3、Azure、SMB)、root 账户、池密钥、用户账户、OTP 密钥和邮件服务器设置的配置与凭据。

条件与“我受影响吗?”相同:受影响的 Xen Orchestra 版本、攻击者可访问的 REST API,以及集合中至少一个未过期令牌。供应商表示该缺陷正在被实际利用,因此面向互联网的实例即使在找到令牌之前也应视为已暴露。

为什么修复有效?

修复在令牌标识符到达集合之前进行验证,并且只使用已验证字段构建查询。它增加了字符串检查并更改了查询:

+const isNonEmptyString = value => typeof value === 'string' && value.length !== 0
+
 export default class {
@@
     this.registerAuthenticationProvider(async ({ token: tokenId }, { ip } = {}) => {
-      if (!tokenId) {
+      if (!isNonEmptyString(tokenId)) {
         return
       }
@@
-  async _getAuthenticationToken(id, properties) {
-    const token = await this._tokens.first(properties ?? id)
+  async _getAuthenticationToken(id, userId) {
+    if (!isNonEmptyString(id) || (userId !== undefined && !isNonEmptyString(userId))) {
+      return
+    }
+
+    // build the query from validated fields only, never forward caller-supplied objects
+    const token = await this._tokens.first(userId === undefined ? id : { id, user_id: userId })

getAuthenticationToken 现在只从输入中取出 id 和 user_id,并将这些值传给私有查询。解码为 {} 的 Cookie 会在任何数据库查询之前失败于字符串检查。有效的字符串令牌仍然可用,复合的 { id, user_id } 查询也得以保留。攻击者向对象添加的额外键会被忽略。

该修复对所述路径是完整的。供应商公告称 REST API、登录路由和 JSON-RPC session.signIn 方法现在会拒绝非字符串和空令牌 ID。它不覆盖使用自己的对象调用令牌提供程序的第三方代码,因此请让实例远离互联网。

如何检查是否已遭入侵?

供应商表示成功的未认证访问不会留下日志条目,因此数据包捕获是最直接的检查。在 Xen Orchestra 主机或其反向代理上捕获流量,并搜索 Cookie 模式,包括编码形式:

tcpdump -i any -A -s 0 'tcp port 80 or tcp port 443' | grep -iE 'authenticationToken=j:(%7B%7D|\{\})'
grep -iE 'authenticationToken=j:(%7B%7D|\{\})' /var/log/nginx/access.log

同一请求在供应商指标中表现为 authenticationToken=j:%7B%7D 或 authenticationToken=j:{}。命中是线索:合法客户端不应将空对象作为令牌发送。

检查 XCP-ng 主机上的活动痕迹:

xe vm-list params=name-label,platform | grep -B1 'hvm_serial: file'
zgrep -- '-serial file:' /var/log/xensource.log*
ls -la /etc/ld.so.preload /.ustar* /etc/cron.d/zz-ustar*

供应商指标包括名为 pivot2 的虚拟机、使用 hvm_serial: file 参数配置的 VM,以及文件 /etc/cron.d/zz-ustar2、/etc/cron.d/zz-ustar、/.ustar5 和 /.ustar6。它还列出 IP 地址 91.211.251.112、193.148.56.72、37.221.208.216、45.66.35.11、64.65.0.120、64.65.62.160、89.47.51.90 和 92.60.37.247,以及 Tor 域名 ustar3rqxgnskzgnwkgpofgtvxevm6cx3lxdbwt4mndtveqyaohid.onion。

如果发现其中任何一项,请轮换控制台可访问的所有凭据并重建实例。供应商表示仅靠清理无法保证移除所有后门。

时间线

  • 2026-11-10 08:29 UTC:修复提交 50166fe3 作为 pull request #10748 合并。
  • 2026-11-10:Vates 发布 VSA-2026-062 以及修复后的 Xen Orchestra 6.9.2 和 6.10.1。
  • 2026-11-10:供应商报告来自所列 IP 地址和 Tor 域名的实际利用。

2026 年 11 月 10 日修复、披露和利用报告的时间线
图 1:Vates 在同一天合并修复、发布公告并报告实际利用。来源:Vates 公告和 pull request #10748,2026 年 11 月 11 日核查

常见问题

有 CVE 吗?

截至 2026 年 11 月 11 日没有分配 CVE。供应商以 VSA-2026-062 跟踪该问题,公告是权威记录。没有 CVE 并不意味着紧迫性降低:供应商表示它正在被实际利用。

这直接影响 XCP-ng 主机吗?

缺陷在 Xen Orchestra 中,不在 XCP-ng 主机软件中。主机之所以面临风险,是因为 Xen Orchestra 使用特权凭据管理它们。接管控制台的攻击者可以利用该访问在主机上执行命令,这就是供应商描述完全接管节点的原因。

应该安装哪个版本?

在稳定通道安装 Xen Orchestra 6.9.2,在最新通道安装 6.10.1。从源码安装时,更新到最新 master 并确认 xo-server 为 5.211.2 或 5.213.1。Appliance 更新包含相同的修复。

拒绝 authenticationToken=j:{} 和 authenticationToken=j:%7B%7D 的规则可以阻止该活动的请求,但供应商警告其他编码可以绕过狭窄的正则。仅在更新前使用该规则,并让实例远离互联网。

它是否被作为零日利用?

供应商表示该缺陷正在被实际利用,但没有说明活动何时开始,也没有说明攻击是否早于修复。它也没有说明该漏洞是否被用作零日。请将暴露窗口视为未知,并检查主机上的所列痕迹。

入侵后应轮换什么?

轮换 Appliance 可访问的所有凭据:池密钥、主机 root 密码、Xen Orchestra 用户账户、OTP 密钥、代理配置、NFS、S3、Azure 和 SMB 备份目标凭据,以及邮件服务器密码。轮换后从已知良好的镜像重建 Appliance。

使用 Ostorlab 查找暴露的 Xen Orchestra 控制台

Ostorlab 的攻击面发现可清点环境中面向互联网的主机,让你在修补前了解哪些 Xen Orchestra 控制台和管理接口可从网络外部响应。使用该清单找出应放在管理网络中的控制台,并优先处理仍然暴露的实例。

参考文献

  • Vates 公告 VSA-2026-062:https://docs.vates.tech/security-advisories/advisories/2026/vates-sa-2026-062/(2026 年 11 月 11 日核查)
  • 修复 pull request #10748:https://github.com/vatesfr/xen-orchestra/pull/10748(2026 年 11 月 11 日核查)
  • 修复提交 50166fe3:https://github.com/vatesfr/xen-orchestra/commit/50166fe3a49c02069d35ba9046ca4a1f77f4e11d(2026 年 11 月 11 日核查)
  • 父提交中易受攻击的 authentication.mjs:https://github.com/vatesfr/xen-orchestra/blob/724402733b2381d93372db0183e21df9d2c457f7/packages/xo-server/src/xo-mixins/authentication.mjs(2026 年 11 月 11 日核查)
  • 父提交中易受攻击的 rest-api.mjs:https://github.com/vatesfr/xen-orchestra/blob/724402733b2381d93372db0183e21df9d2c457f7/packages/xo-server/src/xo-mixins/rest-api.mjs(2026 年 11 月 11 日核查)
  • Xen Orchestra 仓库:https://github.com/vatesfr/xen-orchestra(2026 年 11 月 11 日核查)
  • 社区 Xen Orchestra 容器镜像:https://hub.docker.com/r/ronivay/xen-orchestra(2026 年 11 月 11 日核查)