背景:OCI Compose构件与远程包含
Docker Compose为数百万工作流提供支持,从CI/CD运行器、本地开发环境到云工作空间和企业构建管道。开发者信任它作为Docker Engine之上的友好层,能将几行YAML转换成运行中的应用程序。
2025年10月初,在研究Docker Compose对基于OCI的Compose构件的新支持时,我发现了一个高危路径遍历漏洞。该漏洞允许攻击者通过诱使用户引用恶意远程构件,即可逃离Compose的缓存目录并在主机系统上写入任意文件。该问题已被Docker团队修补并分配为CVE-2025-62725,评级为高危(CVSS 8.9)。
我们强烈建议升级到Docker v2.40.2或更高版本。在本文中,我将解析该漏洞,分享概念验证,并重构实际 exploitation 过程。
为使Compose项目更具可移植性,Docker增加了对获取发布为OCI构件的Compose文件的支持。这允许开发者将Compose项目托管在注册表中,并通过简单的"include:“指令包含它们。
在后台,Compose获取OCI清单,下载每个层,并在缓存目录内重建本地项目。
每个层可以包含注解,例如:
com.docker.compose.filecom.docker.compose.envfilecom.docker.compose.extends
这些注解指示Compose将文件写入何处以及是否扩展主项目定义。
Docker Compose OCI构件中的路径遍历
易受攻击的代码位于pkg/remote/oci.go中,具体在pullComposeFiles、writeComposeFile和writeEnvFile函数内部。
当Compose处理OCI层时,它信任告诉它在哪里写入文件的层注解。攻击者可以设置如下注解:
|
|
然后,Compose在其本地缓存目录和该注解之间执行字面连接:
|
|
没有规范化,没有规范化,没有检查结果路径是否保持在缓存目录内。因此,精心构造的注解可以遍历出缓存目录,并导致Compose在Compose进程有写入权限的任何地方写入文件。
大多数人都知道在不受信任的compose文件上运行"docker compose up"是不好的主意。这个漏洞的微妙和危险之处在于,它在构件解析期间触发,而不仅仅是在启动容器时。许多看似"只读"的命令,例如docker compose ps或docker compose config,会强制Compose获取远程OCI构件并将其重建到缓存中,从而触发漏洞。
利用过程
为了演示该漏洞,我创建了一个最小的OCI注册表,提供包含路径遍历层的恶意Compose构件。该注册表可在此处获取。
攻击者可以通过诱使受害者在包含特制docker-compose.yaml文件的目录中运行几乎任何Compose命令(例如"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"。