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. 基本信息

Item
Details
NickName
nvc-ldcache-overwrite
Project
nvidia-container-toolkit
Introduce Date
2022-04-07
Discovery Date
2025-03-13
Publish Date
2025-07-15
Confirm Link
https://nvidia.custhelp.com/app/answers/detail/a_id/5659
CVE-ID
CVE-2025-23267
Exploits
github.com/ssst0n3/poc-nvc-ldcache-overwrite
Affect Version
>= v1.10.0-rc.1
CVSS
NVIDIA: 8.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:L/A:H

ssst0n3: 9.0 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
Author
LEI WANG (github-id: ssst0n3) 
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

CVE-2025-23267挖掘报告: GPU容器逃逸再现

容器逃逸并反弹shell:

CVE-2025-23267挖掘报告: GPU容器逃逸再现

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(&#34;failed to load container state: %v&#34;, err)
 }

 containerRootDir, err := s.GetContainerRoot()
if err != nil {
return fmt.Errorf(&#34;failed to determined container root: %v&#34;, err)
 }

 ldconfigPath := m.resolveLDConfigPath(cfg.ldconfigPath)
 args := []string{filepath.Base(ldconfigPath)}
if containerRootDir != &#34;&#34; {
  args = append(args, &#34;-r&#34;, containerRootDir)
 }

 containerRoot := containerRoot(containerRootDir)

if containerRoot.hasPath(&#34;/etc/ld.so.cache&#34;) {
  args = append(args, &#34;-C&#34;, &#34;/etc/ld.so.cache&#34;)
 } else {
  m.logger.Debugf(&#34;No ld.so.cache found, skipping update&#34;)
  args = append(args, &#34;-N&#34;)
 }

 folders := cfg.folders.Value()
if containerRoot.hasPath(&#34;/etc/ld.so.conf.d&#34;) {
  err := m.createLdsoconfdFile(containerRoot, ldsoconfdFilenamePattern, folders...)
if err != nil {
   return fmt.Errorf(&#34;failed to update ld.so.conf.d: %v&#34;, 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, &#34;-f&#34;, &#34;/etc/ld.so.conf&#34;)

return m.SafeExec(ldconfigPath, args, nil)
}

6. 时间线

  • 2025-03-13 我们发现漏洞

  • 2025-04-02 完成容器逃逸完整漏洞利用

  • 2025-04-04 向 NVIDIA 社区报告漏洞

  • 2025-07-15 NVIDIA发布漏洞公告

  • 2025-07-18 我在公众号发布本文