CVE-2025-23267挖掘报告: GPU容器逃逸再现
原文链接: https://mp.weixin.qq.com/s?__biz=MzA4NTAxMjA5Mg==&mid=2247484495&idx=1&sn=4f565a89e230b4cfbbfb7df78fa9706a
CVE-2025-23267挖掘报告: GPU容器逃逸再现
原创 ssst0n3,e3pem 石头的安全料理屋 2025-07-18 11:10
CVE-2025-23267: GPU容器逃逸再现
——nvidia-container-toolkit CVE-2025-23267 主机 ldcache 覆盖漏洞挖掘报告
1. 基本信息
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MIN YAO (github-id: e3pem) |
2. 组件简介
NVIDIA Container Toolkit是由NVIDIA公司推出的一套工具,用于在容器化环境中实现GPU加速计算。它允许用户在Docker等容器平台中使用NVIDIA GPU,从而在容器中运行需要GPU支持的应用程序,如深度学习训练、推理、科学计算等。
漏洞产生于 nvidia-container-toolkit 的 nvidia-cdi-hook/update-ldcache 命令中,用于在挂载 nvidia so 库到容器后更新 ld.so.cache。
3. 漏洞介绍
3.1 漏洞描述
update-ldcache
调用了主机
ldconfig
命令,指定了该命令使用了 ldconfig 内置的
-r
参数来 chroot 到容器 rootfs ,但未给 ldconfig 命令提供沙箱,因此可以通过 procfs 来实现路径穿越。
在 ldconfig 命令写入
/etc/ld.so.cache
,
/var/cache/ldconfig/aux-cache
等文件时,如果相关路径是软链接,则可以覆盖主机对应文件,也可以写入到主机任意位置。
其中 ld.so.cache 是 Linux 系统中动态链接器(ld.so 或 ld-linux.so)使用的关键缓存文件,用于加速共享库(.so 文件)的查找过程。当程序启动需要动态链接共享库时,动态链接器(ld.so)会直接读取 ld.so.cache,而不是实时遍历所有目录。如果攻击者篡改 ld.so.cache,可能导致合法库路径被指向攻击者控制的恶意共享库,进而实现容器逃逸。
3.2 影响
3.2.1 范围
影响版本:nvidia-container-toolkit >= v1.10.0-rc.1
特别地:
– 对 nvidia-container-toolkit < v1.17.5, 该漏洞在 CDI 模式生效。
- 对 nvidia-container-toolkit >= v1.17.5, 该漏洞在 CDI, legacy 模式均生效。
3.2.2 危害
覆盖主机
/etc/ld.so.cache
,
/var/cache/ldconfig/aux-cache
等文件,或在主机任意位置写入相应文件,进而导致容器逃逸。
4. 漏洞利用效果
覆盖主机 ld.so.cache
容器逃逸并反弹shell:
5. 漏洞分析
在调用
ldconfig
命令时,除了其自身的 chroot 机制外,未提供其他保护。
https://github.com/NVIDIA/nvidia-container-toolkit/blob/main/cmd/nvidia-cdi-hook/update-ldcache/update-ldcache.go#L125
func (m command) run(c *cli.Context, cfg *options) error {
s, err := oci.LoadContainerState(cfg.containerSpec)
if err != nil {
return fmt.Errorf("failed to load container state: %v", err)
}
containerRootDir, err := s.GetContainerRoot()
if err != nil {
return fmt.Errorf("failed to determined container root: %v", err)
}
ldconfigPath := m.resolveLDConfigPath(cfg.ldconfigPath)
args := []string{filepath.Base(ldconfigPath)}
if containerRootDir != "" {
args = append(args, "-r", containerRootDir)
}
containerRoot := containerRoot(containerRootDir)
if containerRoot.hasPath("/etc/ld.so.cache") {
args = append(args, "-C", "/etc/ld.so.cache")
} else {
m.logger.Debugf("No ld.so.cache found, skipping update")
args = append(args, "-N")
}
folders := cfg.folders.Value()
if containerRoot.hasPath("/etc/ld.so.conf.d") {
err := m.createLdsoconfdFile(containerRoot, ldsoconfdFilenamePattern, folders...)
if err != nil {
return fmt.Errorf("failed to update ld.so.conf.d: %v", err)
}
} else {
args = append(args, folders...)
}
// Explicitly specify using /etc/ld.so.conf since the host's ldconfig may
// be configured to use a different config file by default.
args = append(args, "-f", "/etc/ld.so.conf")
return m.SafeExec(ldconfigPath, args, nil)
}
6. 时间线
-
2025-03-13 我们发现漏洞
-
2025-04-02 完成容器逃逸完整漏洞利用
-
2025-04-04 向 NVIDIA 社区报告漏洞
-
2025-07-15 NVIDIA发布漏洞公告
-
2025-07-18 我在公众号发布本文