一句话版本
"容器逃逸"指运行在容器里的程序突破隔离,获得宿主机的控制权。绝大多数逃逸不需要高深的漏洞,而是因为配置太宽松:以特权模式运行、把 Docker 的控制接口挂进了容器、给了不必要的内核能力、挂载了宿主机的敏感目录。剩下的少数才是真正的漏洞:容器运行时(如 runc)或 Linux 内核本身的缺陷。 对 AI Agent 来说,这意味着:把 Agent 放进容器并不自动安全,配置决定一切。
全文分三层:
- 通俗理解:房间的门锁没问题,是你把备用钥匙挂在了门内侧
- 实际用处:runc 的两次著名漏洞、内核漏洞、错误配置的常见形态
- 原理与工程要点:逃逸的几类根因、加固清单、如何检测
第一层:通俗理解
1.1 门锁没问题,钥匙挂在门内
一个房间的门锁很结实,但为了方便:
- 房间里放了一把万能钥匙(特权模式);
- 房间墙上开了一个直通大楼控制室的窗口(Docker socket);
- 房间的一面墙其实是另一个房间的墙(挂载宿主机目录)。
住在里面的人不需要撬锁,直接走出去就行了。
1.2 两类原因
| 类别 | 占比 | 例子 |
|---|---|---|
| 错误配置 | 绝大多数 | 特权模式、挂载 Docker socket、过多能力、挂载宿主敏感目录、以 root 运行 |
| 软件漏洞 | 少数,但影响大 | 容器运行时漏洞、Linux 内核漏洞 |
第二层:实际用处
| 事件 | 类型 | 说明 |
|---|---|---|
| runc CVE-2019-5736 | 运行时漏洞 | 容器内的恶意进程可以覆盖宿主机上的 runc 二进制文件,下一次有人在宿主机上执行容器命令时就会运行攻击者的代码。影响 Docker、Kubernetes 等几乎所有使用 runc 的平台 |
| Leaky Vessels(2024,含 runc CVE-2024-21626) | 运行时漏洞 | 一组漏洞,其中最严重的一个与文件描述符泄露有关,可以让容器进程访问宿主机文件系统 |
| Dirty Pipe(2022,CVE-2022-0847) | 内核漏洞 | Linux 内核管道机制的漏洞,允许改写只读文件,可用于提权和容器逃逸 |
| 加密货币挖矿事件(大量) | 错误配置 | 攻击者扫描互联网上未加认证暴露的 Docker API 或 Kubernetes 面板,直接创建特权容器挖矿 |
这几起运行时和内核漏洞都在披露后很快发布了补丁。及时更新是最基本的防线。
第三层:原理与工程要点
3.1 错误配置的常见形态
| 配置 | 为什么危险 |
|---|---|
--privileged |
几乎关闭了所有隔离:能访问所有设备、拥有所有内核能力 |
挂载 /var/run/docker.sock |
容器里的程序可以控制宿主机上的 Docker,创建一个挂载宿主根目录的新容器 |
添加 CAP_SYS_ADMIN 等高危能力 |
这个能力涵盖了大量特权操作,常被称为"新的 root" |
挂载宿主机的 /、/etc、/proc、/sys 或用户主目录 |
直接读写宿主机文件 |
| 共享宿主机的 PID、网络命名空间 | 能看到并影响宿主机的进程和网络 |
| 在容器里以 root 运行,且未启用用户命名空间 | 一旦逃逸就是宿主机 root |
| 云元数据接口可达 | 容器里可以拿到宿主机所在云实例的临时凭证(见《SSRF》) |
对 AI 编程 Agent 来说,一个特别常见的诱惑是:为了让 Agent 能"构建 Docker 镜像",把 Docker socket 挂进 Agent 的容器。这相当于把宿主机的控制权交给了 Agent。
3.2 加固清单
| 措施 | 说明 |
|---|---|
| 不用特权模式,不挂 Docker socket | 需要构建镜像时,使用无守护进程的构建工具或单独的构建服务 |
| 删除所有能力,再按需添加 | --cap-drop=ALL |
| 以非 root 用户运行;启用用户命名空间(rootless) | 即使逃逸也不是宿主 root |
| 使用默认或更严格的 seccomp / AppArmor / SELinux 配置 | 限制系统调用和文件访问 |
| 根文件系统只读 | --read-only,只给必要的可写临时目录 |
no-new-privileges |
防止通过 setuid 程序提权 |
| 资源限制 | CPU、内存、进程数,防止耗尽宿主资源 |
| 阻断云元数据接口 | 或强制使用需要令牌的 IMDSv2 |
| 及时更新内核和运行时 | 运行时和内核漏洞的补丁通常很快发布 |
| 对不可信代码使用更强隔离 | gVisor、微型虚拟机(见《沙箱的几层》) |
3.3 检测
- 配置扫描:在部署前用工具检查容器和 Kubernetes 配置是否存在上述高危项;
- 运行时监控:用 Falco 等工具监控容器内的异常行为,比如在容器里启动 shell、访问 Docker socket、修改敏感文件、加载内核模块;
- 定期红队演练:在测试环境里模拟"Agent 已被完全控制",看它能走多远(见《威胁建模与红队测试》)。
3.4 一句话原则
容器不是为"运行不可信代码"而设计的安全边界,它首先是打包和资源隔离工具。要运行真正不可信的代码(包括被注入后的 AI Agent 可能写出的任何东西),就要在容器之外再加一层更强的隔离。
总结
| 层次 | 要点 |
|---|---|
| 直觉 | 门锁结实,但钥匙挂在门内(错误配置) |
| 两类根因 | 错误配置(多数)、运行时和内核漏洞(少数) |
| 高危配置 | 特权模式、Docker socket、高危能力、挂载宿主目录、root 运行 |
| 加固 | 删能力、非 root、只读、seccomp、及时更新、不可信代码用更强隔离 |