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

深度解析

深度解析

Dokploy:成员账户可获取主机 root 的 RCE

Dokploy 成员可在数据库密码中注入反引号,以 root 身份在主机上执行命令;修复仅在 canary 分支。

TL;DR

  • Dokploy 组织中能够创建数据库服务的成员,可以以 root 身份在主机上执行命令。方法是在数据库密码中放入反引号(验证器允许),或在数据库用户名中放入分号(用户名没有任何验证器)。
  • Dokploy v0.29.0 至 v0.31.0 受影响,2026 年 11 月 5 日发布的 v0.31.0 是当前易受攻击版本。攻击者需要拥有服务创建权限的成员账户;这不是未认证漏洞。
  • 此问题没有分配 CVE 或 CVSS 评分。研究者报告了针对官方 v0.31.0 镜像的实机验证,并指出 Dokploy 在 CVE-2026-72868 中将同一前提条件类别评为 9.9。没有已知的在野利用;截至 2026 年 11 月 10 日,该问题也未列入 CISA 的 Known Exploited Vulnerabilities (KEV) 目录。
  • 修复已合并到 Dokploy 的 canary 分支,未进入带标签的发布版。立即撤销不可信成员的服务创建权限。应用补丁或等待包含修复的版本。参见“如何修复?”。

我受影响吗?

以下条件必须全部成立:

  • 你运行自托管 Dokploy v0.29.0 至 v0.31.0。易受攻击的密码验证器在 v0.29.0 引入,研究者称它在所有分支上都没有变化。
  • 你给组织成员授予服务创建权限和数据库服务访问权限。Dokploy 的 changePassword 过程在执行数据库命令前检查 service: ["create"]。
  • 该成员能够访问面板。在单管理员安装中,没有需要跨越的边界,因为管理员已经拥有该权限。

研究者测试了官方 dokploy/dokploy v0.31.0 镜像并报告了实机验证。修复是合并 canary 分支上 pull request #5910 的提交 1c862c9cb0,合并时间为 2026 年 11 月 9 日 16:59 UTC。发布标签止于 v0.31.0。

分支 受影响版本 修复版本
自托管 Dokploy v0.29.0 至 v0.31.0 截至 2026 年 11 月 10 日没有带标签的发布版;修复在 canary 的 pull request #5910 中

检查正在运行的镜像和版本:

docker inspect --format '{{.Config.Image}}' dokploy
docker images dokploy/dokploy

面板也会在界面中显示版本。标签为 v0.29.0 至 v0.31.0 的镜像受影响。包含 pull request #5910 的 canary 构建有修复,但它不是发布版。

如何修复?

目前没有修复版本。修复已合并到 canary,因此选择以下一种方式:

  1. 构建或拉取包含 pull request #5910 canary 提交的 Dokploy 镜像,然后重新部署面板。在依赖它之前,确认构建在数据库路由中包含 quote() 调用。
  2. 如果无法运行 canary 构建,对构建应用相同更改:docker exec <container> 之后的每个参数都通过 shell-quote 包的 quote()。
  3. 在面板修复前,撤销所有不需要的成员的服务创建权限。把能够创建数据库的成员视为主机 root 等价。
  4. 将 Dokploy 面板访问限制在可信网络,不要直接暴露到互联网。
  5. 检查审计日志中无法解释的数据库密码更改,如发现则轮换数据库凭据。
  6. 关注点名 pull request #5910 或此修复的 Dokploy 带标签发布版,然后升级并确认版本。

研究者的论文是修复范围的参考。该 pull request 更改 Postgres、MySQL、MariaDB、MongoDB 和 Redis 的密码路径。

根本原因是什么?

Dokploy 的密码验证器阻止多个 shell 字符,但允许反引号、分号、管道、与号、括号和重定向。changePassword 过程随后把密码插入由 bash 解析的 docker exec 命令,数据库用户名则完全没有验证器。

以下是 v0.31.0 中 apps/dokploy/server/src/db/schema/utils.ts 的验证器:

/** Database password: blocks shell-dangerous characters like $ ! ' " \ / and spaces. */
export const DATABASE_PASSWORD_REGEX =
    /^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/;

注释列出了被阻止的字符。字符类仍然包含 `、;、|、&、(、)、> 和 <。这足以进行命令替换和第二条命令。

以下是 v0.31.0 中 Postgres 的 changePassword 过程:

const command = `docker exec ${container.Id} psql -U ${databaseUser} -d postgres -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';"`;

await db.transaction(async (tx) => {
  ...
  if (serverId) {
    await execAsyncRemote(serverId, command);
  } else {
    await execAsync(command, { shell: "/bin/bash" });
  }
});

databaseUser 来自存储的 Postgres 记录,没有验证器。它被放在 -U 之后,没有引号。密码位于单引号中,但整个 -c 参数位于双引号中。bash 会在双引号内展开反引号和 $(),因此像 P2`id` 这样的密码会在 shell 构建命令时执行 id。databaseUser 中的分号会结束命令并开始另一条命令。

命令通过 execAsync 以 /bin/bash 在 Dokploy 服务器进程中运行。该进程是服务器容器中的 root,容器持有主机的 Docker socket。那里的命令执行实际上就是主机 root。

MySQL、MariaDB 和 MongoDB 路由中存在相同的构造。研究者报告触发了 Postgres 和 MySQL 路径,并称另外两个在源码上相同。Redis 路径把密码放在顶层单引号中,没有触发,这是证明该机制的对照。

如何被利用?

能够创建数据库服务的成员把密码或用户名改为关闭 shell 引用的值,Dokploy 服务器便以 root 执行注入的命令。

  1. 攻击者以拥有服务创建权限的组织成员身份登录 Dokploy,或者在他们已经控制组织时创建这样的成员。
  2. 攻击者创建一个数据库服务,或使用他们能访问的服务。该服务的 Postgres 记录存储用户名。
  3. 攻击者调用 changePassword,使用一个能通过 DATABASE_PASSWORD_REGEX 但包含反引号的密码,例如 P2`id>x`。验证器接受它,因为没有禁止反引号。
  4. Dokploy 构建 docker exec 命令并交给 /bin/bash。bash 对反引号执行命令替换并运行 id,把输出重定向到攻击者选择的文件。数据库密码更改也同时完成。
  5. 或者,攻击者把数据库用户名设置为包含分号的值。用户名没有验证器,因此到达未加引号的 psql -U 参数并开始第二条命令。
  6. 命令以 root 在 Dokploy 服务器容器中运行。容器持有主机的 Docker socket,因此攻击者可以利用它访问主机和其他租户的服务。

研究者的实机验证先使用无害密码,然后使用被验证器拒绝的 $(id) 密码。随后反引号密码返回 200,并在服务器容器内留下一个读取 uid=0(root) gid=0(root) 的 canary 文件。测试在绑定 localhost 的环境中针对官方 v0.31.0 镜像运行。研究者还报告触发 MySQL 路径作为第二个入口,以及带分号的用户名作为第三个入口。

没有已知的在野利用。公开记录是研究者的 oss-security 消息、其链接的论文和已合并的修复。

攻击如何展开?

拥有服务创建权限的成员提交一个验证器接受的密码,密码到达 docker exec 内的 bash 命令。bash 随后在持有主机 Docker socket 的容器中以 root 执行注入的命令。

flowchart LR A["拥有服务创建权限的成员"] --> B["用反引号调用 changePassword"] B --> C["验证器允许反引号"] C --> D["字符串构建进 docker exec 命令"] D --> E["bash 命令替换执行载荷"] E --> F["Dokploy 容器内的 root"] F --> G["主机 Docker socket"] G --> H["主机 root 和其他租户的秘密"]

攻击者能做什么?

触发注入的攻击者以 root 在 Dokploy 服务器容器中执行命令,并可通过其 Docker socket 访问主机。这等于控制面板、它管理的每台服务器以及每个租户的秘密。

条件也是影响的一部分:

  • 攻击者需要拥有服务创建权限和数据库服务访问权限的已认证 Dokploy 成员账户。研究者明确指出这不是未认证,也不是跨组织故障。
  • 在单管理员安装中,管理员已经拥有该权限,因此面板用户与主机之间没有边界。
  • 命令以 root 在服务器容器中运行。该容器按设计挂载或访问主机的 Docker socket,因此攻击者可以启动特权容器、读取其他服务的环境变量并访问主机文件系统。
  • 注入在提交密码更改时触发。数据库密码也会更改,因此操作在载荷运行时可能看起来成功。
  • 没有已知的在野利用,也没有点名受害者。

影响是主机级别,而不是数据库级别。能够创建数据库的成员已经受信任管理该服务;此缺陷把这种信任变成对主机和其他租户的控制。

为什么修复有效?

修复使用 shell-quote 的 quote() 从参数数组构建每个 docker exec 命令,因此密码和用户名保持为单个参数,bash 不再把其内容解析为语法。

以下是 pull request #5910 对 apps/dokploy/server/api/routers/postgres.ts 的更改:

-           const command = `docker exec ${container.Id} psql -U ${databaseUser} -d postgres -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';"`;
+           const command = `docker exec ${container.Id} ${quote([
+               "psql",
+               "-U",
+               databaseUser,
+               "-d",
+               "postgres",
+               "-c",
+               `ALTER USER "${databaseUser}" WITH PASSWORD '${password}';`,
+           ])}`;

quote() 为每个参数返回经过 shell 引用的字符串,因此 databaseUser 或 password 中的反引号或分号留在其参数内。SQL 语句仍然是一个 -c 参数,数据库收到字面密码。pull request 说密码在 SQL 字符串内仍然安全,因为验证器禁止单引号。

相同的重写覆盖 MySQL、MariaDB、MongoDB 和 Redis 路由。修复没有改变验证器,因此成员仍然可以设置带反引号的密码;区别是反引号不再到达 shell。

如何检查是否已遭入侵?

没有公开的入侵指标。检查面板的审计日志和数据库记录,寻找利用所需的输入。

  • 检查 Dokploy 审计日志中无法解释的数据库密码更改和数据库服务创建。changePassword 过程在命令运行后写入审计条目。
  • 检查存储的数据库密码和用户名中是否有反引号、分号、管道或其他 shell 元字符。验证器允许但看起来像 shell 语法的值是线索。
  • 查找 Dokploy 服务器容器中的异常文件,尤其是数据库命令创建的 canary 文件或 shell 脚本。
  • 检查服务器容器中是否有异常的 root 进程、新的特权容器和出站连接,并检查主机的 Docker 事件中是否有不是你启动的容器。
  • 如果发现线索,在重建主机前保留面板数据库、服务器容器和 Docker 事件。轮换面板存储的每个数据库和服务凭据。

失败的注入可能只留下密码更改的审计条目,没有其他痕迹。审计条目本身不能证明利用。

时间线

  • 2026-11-05:Dokploy 发布 v0.31.0,这是当前版本,也是研究者测试的版本。
  • 2026-11-07:pull request #5910“fix(security): database changePassword command injection (all 5 DB types)”被打开。
  • 2026-11-09 16:59 UTC:pull request 合并到 canary 分支。没有带标签的发布版包含它。
  • 2026-11-10 02:11 UTC:研究者在 oss-security 邮件列表发布实机验证的披露。

从易受攻击版本到公开披露仅五天
图 1:v0.31.0 于 11 月 5 日发布,修复于 11 月 9 日合并到 canary,披露于 11 月 10 日跟进。来源:Dokploy 发布和 pull request #5910,2026 年 11 月 10 日检查

常见问题

Dokploy 缺陷是未认证的吗?

不是。攻击者需要拥有服务创建权限和数据库服务访问权限的已认证组织成员。研究者明确说明前提条件,并表示这不是跨组织故障。

Dokploy v0.31.0 修复了吗?

没有。v0.31.0 是当前版本,也是研究者测试的版本。修复在 canary 分支的 pull request #5910 中,于 2026 年 11 月 9 日合并;截至 2026 年 11 月 10 日没有带标签的发布版包含它。

此问题有 CVE 吗?

截至 2026 年 11 月 10 日没有分配 CVE。Dokploy 将同一前提条件类别的另一个缺陷 CVE-2026-72868 评为 CVSS v3.1 9.9;该评分属于较早的 destination.testConnection 注入,不属于此问题。

有公开的利用代码吗?

研究者公开了方法、实机验证和论文,验证可在官方 v0.31.0 镜像上复现。公开消息没有链接独立的利用代码仓库。

我应该把每个 Dokploy 成员都视为 root 吗?

能够创建数据库服务的成员可以通过此缺陷获得主机 root,因此就该权限而言是。撤销不需要的成员的服务创建权限,并把面板本身视为 root 等价系统。

这影响托管的 Dokploy 服务吗?

Dokploy 是可自托管的软件。披露和修复针对自托管面板。公开记录没有点名任何托管服务,因此本文不对其作出声明。

参考文献

  • 研究者的 oss-security 披露“Dokploy: the validator allows the backtick : a member's database password change is host RCE, 9.9 on the vendor's own vector (v0.31.0, live-proven)”,2026 年 11 月 9 日,包含实机验证、范围和论文链接:https://www.openwall.com/lists/oss-security/2026/11/10/2(2026 年 11 月 10 日检查)
  • Dokploy pull request #5910“fix(security): database changePassword command injection (all 5 DB types)”,2026 年 11 月 7 日打开,2026 年 11 月 9 日合并:https://github.com/Dokploy/dokploy/pull/5910(2026 年 11 月 10 日检查)
  • v0.31.0 中 apps/dokploy/server/src/db/schema/utils.ts 的易受攻击 DATABASE_PASSWORD_REGEX:https://github.com/Dokploy/dokploy/blob/v0.31.0/apps/dokploy/server/src/db/schema/utils.ts#L50-L52(2026 年 11 月 10 日检查)
  • v0.31.0 中 apps/dokploy/server/api/routers/postgres.ts 的易受攻击 Postgres changePassword 命令:https://github.com/Dokploy/dokploy/blob/v0.31.0/apps/dokploy/server/api/routers/postgres.ts#L448(2026 年 11 月 10 日检查)
  • Dokploy v0.31.0 发布,2026 年 11 月 5 日公布:https://github.com/Dokploy/dokploy/releases/tag/v0.31.0(2026 年 11 月 10 日检查)
  • CVE-2026-72868 记录,较早的 Dokploy destination.testConnection rclone 注入,CVSS v3.1 9.9,作为供应商对同一前提条件类别的评分引用:https://www.cve.org/CVERecord?id=CVE-2026-72868(2026 年 11 月 10 日检查)
  • dokploy/dokploy 的 Docker Hub 仓库,16,116,660 次拉取,2026 年 11 月 10 日检查:https://hub.docker.com/r/dokploy/dokploy(2026 年 11 月 10 日检查)
  • CISA Known Exploited Vulnerabilities 目录 JSON 源,2026 年 11 月 10 日检查,没有 Dokploy 条目:https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json(2026 年 11 月 10 日检查)