CVE-2025-62725: From “docker compose ps” to System Compromise
概述
Docker Compose作为Docker Engine之上的友好层,被数百万工作流所信赖,从CI/CD运行器、本地开发环境到云工作空间和企业构建管道。2025年10月初,在探索Docker Compose对基于OCI的Compose构件的新支持时,我发现了一个高严重性的路径遍历漏洞。该漏洞允许攻击者通过诱使用户引用恶意的远程构件,逃离Compose的缓存目录并在主机系统上写入任意文件。Docker团队已对该问题进行了修补,并分配了编号CVE-2025-62725,评级为高危(CVSS 8.9)。
我们强烈建议升级到Docker版本v2.40.2或更高版本。在本文中,我将剖析此漏洞,分享概念验证,并重构其在实践中可能发生的利用过程。
背景:OCI Compose构件与远程包含
为了使Compose项目更具可移植性,Docker增加了对获取以OCI构件形式发布的Compose文件的支持。这允许开发者将Compose项目托管在注册表中,并通过简单的"include:"指令包含它们。
在后台,Compose会获取OCI清单,下载每个层,并在缓存目录内重建本地项目。每个层可以包含诸如com.docker.compose.file、com.docker.compose.envfile和com.docker.compose.extends等注解。这些注解指示Compose在何处写入文件以及是否扩展主项目定义。
Docker Compose OCI构件中的路径遍历
易受攻击的代码位于pkg/remote/oci.go中,具体在pullComposeFiles、writeComposeFile和writeEnvFile函数内部。
当Compose处理OCI层时,它信任指示其写入文件位置的层注解。攻击者可以设置如下注解:
|
|
Compose随后会对其本地缓存目录和该注解执行字面连接:
|
|
没有进行归一化,没有规范化,也没有检查生成的路径是否保持在缓存目录内。因此,精心构造的注解可以遍历出缓存目录,并导致Compose在其进程拥有写入权限的任何位置写入文件。
大多数人都知道在不信任的compose文件上运行“docker compose up”是个坏主意。但这个漏洞的微妙和危险之处在于,它在构件解析期间就会被触发,而不仅仅是在启动容器时。许多看似“只读”的命令,例如docker compose ps或docker compose config,都会强制Compose获取远程OCI构件并重建到缓存中,从而触发该漏洞。
利用过程
为了演示该漏洞,我创建了一个最小的OCI注册表,用于提供包含路径遍历层的恶意Compose构件。该注册表可在此处获取。
攻击者可以通过诱使受害者运行几乎任何Compose命令来利用此漏洞,例如在包含特制的docker-compose.yaml文件的目录中运行“docker compose ps”。
一旦触发,Docker Compose CLI将从攻击者的注册表获取远程构件,无意中泄露服务器的IP地址。然后,它会处理构件的注解,盲目地在缓存目录之外写入额外的YAML片段。
在这个概念验证中,有效负载的目标是~/.ssh/authorized_keys,注入攻击者的公钥,并立即授予他们访问受害者机器的SSH权限,即使没有启动任何容器,用户也没有显式调用任何“写”操作。
修复与缓解措施
Docker团队的补丁引入了一个validatePathInBase()函数,该函数在写入前对注解派生的路径进行归一化和验证,拒绝任何解析到缓存目录之外或包含绝对路径的路径。
我们强烈建议升级到Docker版本v2.40.2或更高版本。
时间线
- 2025年10月9日 — 漏洞报告给Docker安全团队。
- 2025年10月21日 — 问题确认,发布安全公告。
- 2025年10月27日 — 修复在Docker Compose v2.40.2中发布,CVE-2025-62725公布。
结论
Docker Compose的OCI构件功能旨在让共享配置变得轻松,但正如本例所示,任何工具在自动从未信任源重建文件时,边界都会变得模糊。
Docker团队的迅速响应和修复确保了用户受到保护,但对整个生态系统的更广泛启示是明确的:清理每一条路径,即使“它只是YAML”。