【CVE-2024-21626】容器逃逸漏洞修复

本文介绍了runc容器中的一个逃逸漏洞,涉及文件描述符泄漏,攻击者可通过恶意镜像或利用runcexec中的漏洞访问宿主机文件系统。文章详细演示了漏洞环境搭建、攻击过程以及官方的修复方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈喽大家好,我是咸鱼。

好久不见,最近有一个很火的 CVE——runc 容器逃逸漏洞。年前的时候我们已经在测试环境进行了相关操作打算年后线上进行修复。

因为今天咸鱼才开工,所以文章也就拖到了现在 😃

漏洞介绍

简单来讲,docker-runc 是一个用 Go 语言编写的 CLI 工具,它利用 Linux 的核心功能(如 cgroups 和命名空间)来创建和运行容器。

由于 runc 内部不正确处理文件描述符,导致泄漏关键的宿主机文件描述符到容器中。

容器逃逸方式:

  • 攻击1: 利用文件描述符泄漏,特权用户执行恶意容器镜像,导致 pid1 进程在宿主机挂载命名空间中拥有工作目录,从而允许对整个宿主文件系统的访问。
  • 攻击2: 在 runc exec 中存在文件描述符泄漏和工作目录验证不足,攻击者可通过符号链接将路径替换为 /proc/self/fd/7/,并绕过保护机制,最终通过访问主机文件系统实现攻击。
  • 攻击3: 利用类似 /proc/self/fd/7/../../../bin/bash 的路径作为参数,覆盖主机二进制文件,从而改进攻击1和2。攻击者可以在主机上执行目标二进制文件,获取完全访问主机的权限。

漏洞演示

这部分内容借用卡瓦邦噶的文章《CVE-2024-21626 从容器内逃逸到宿主机文件系统》

环境准备

准备一个新的 VM,需要安装的依赖有:

  • 依赖 golang 1.22 和 libseccomp-dev 来编译指定版本的 runc;
  • 依赖 build-essential 编译 runc;
  • 依赖 docker engine,指定版本的 runc;

第一步:按照官方文档安装最新版本的 docker。

第二步:替换 runc (最新版已经解决这个问题了)到旧版本,这里我们使用 v1.0.0-rc10. 编译脚本如下:

# install golang
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
export GOPATH=~/go
go version

# install dependencies for building runc
apt update
apt install -y build-essential libseccomp-dev

# compile and install runc
cd $GOPATH
mkdir -pv src/github.com/opencontainers
cd src/github.com/opencontainers
git clone https://github.com/opencontainers/runc
cd runc

git checkout v1.0.0-rc10

export GO111MODULE=auto
make
sudo make install

安装完成旧版本的 runc 之后需要重启 docker engine:
sudo systemctl restart docker.

攻击演示

创建一个 Dockerfile:

# Sets the current working directory for this image
WORKDIR /proc/self/fd/7/`

编译这个 docker image: docker build . -t test

最后运行这个 docker image: docker run --rm -ti test

可能一次运行不会成功,多运行几次会成功。

进入 container,此时 cwd 显示

通过相对路径,我们可以回到 Host 上面的 / 了:

打开 Host 上面的文件
如果我们安装运行 htop,会发现只有自己的容器里面的进程:

htop 只显示自己容器的 pid

但是如果我们改变当前容器的 fs root: chroot . ,再次运行 htop,就可以看到所有的进程了。

chroot ps 可以显示所有的 pid

htop 也可以显示所有的 pid
但是试了下发送 signal 开 kill 进程是不行的,我猜是因为 pid namespace 仍然是对进程隔离的?

甚至可以在容器内运行docker 命令,看到所有的 container。因为有了 docker binary 的路径(和权限,因为容器进程也是 root)和 docker socket 的路径。

在容器内 docker ps

漏洞修复

目前官方已有可更新版本,可以参考以下链接升级至最新版本:runc >= 1.1.12

下载链接

下面是咸鱼在自己本地环境的操作(CentOS 7 系统)

1、先看下当前 runc 版本:

2、复制上面的链接进去,下载 runc.amd64 ,然后上传到服务器上(我选择上传到 /opt 目录下)

或者直接在服务器上 wget 也行

cd /opt && wget https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64

4、先备份原本的 runc 工具

mv /usr/bin/runc /usr/bin/runcbak

5、更新 runc

mv /opt/runc.amd64 /usr/bin/runc && chmod +x /usr/bin/runc

6、重启 docker 并检查 runc 是否更新成功

systemctl restart  docker.service 

docker version 
<think>好的,我现在需要处理用户关于CVE-21626的问题,特别是询问在Kubernetes部署中发现containerd 1.6.26是否存在此漏洞。首先,我得回顾一下这个漏洞的基本情况。CVE-21626是一个runc的容器逃逸漏洞,影响容器运行时,可能导致攻击者突破容器隔离,访问宿主机文件系统。 接下来,我需要确认containerd的版本是否受影响。根据之前的知识,containerd在1.6.18及更高版本已经修复了这个漏洞。用户提到的版本是1.6.26,显然高于修复版本,所以理论上不应该存在漏洞。不过,为了确保准确性,我需要再次核实官方资料,比如查看containerd的GitHub发布日志或安全公告,确认修复版本的具体信息。 然后,考虑到用户可能是在K8S环境中使用containerd,需要解释即使containerd版本已经修复,但runc的版本同样关键。因为containerd可能依赖特定版本的runc,用户需要检查runc是否也更新到了修复版本。例如,如果containerd 1.6.26捆绑的runc版本是否已经包含补丁,或者是否单独安装了旧版runc。 此外,用户可能需要指导如何验证当前环境中runc的版本。可以通过在节点上执行runc -v命令来检查,或者通过容器运行时的配置查看。同时,提醒用户即使containerd版本正确,如果runc未更新,仍然存在风险。 另外,用户可能关心如何升级containerd或runc,需要提供简要的步骤,比如使用包管理器更新,或者手动替换runc二进制文件,并重启containerd服务。同时,注意升级过程中可能对运行中的容器产生影响,建议在维护窗口进行操作。 最后,应该建议用户进行全面检查,包括所有节点的运行时版本,确保一致性,避免遗漏某些节点未更新导致的安全隐患。另外,提及监控和日志的重要性,以及应用安全补丁的最佳实践,比如定期更新、使用漏洞扫描工具等。 总结下来,我需要确保回答准确,涵盖漏洞影响、版本验证步骤、修复方法以及后续的安全建议,同时用用户容易理解的语言表达,避免过于技术化的术语,但又要提供足够的信息供他们操作。</think>--- ### 一、漏洞背景:**CVE-21626(runc容器逃逸漏洞)** 1. **漏洞本质** - **runc** 是容器运行时底层工具(被 containerd、Docker 等调用),负责创建容器进程。 -漏洞允许攻击者通过特定配置的容器镜像或容器启动参数,绕过容器隔离机制,访问宿主机文件系统(**容器逃逸**),可能导致敏感信息泄露或宿主机被控制。 2. **影响范围** - **受影响版本**:runc <= 1.1.11 - **间接影响组件**: - containerd < 1.6.18(默认捆绑旧版 runc) - Docker < 24.0.7(依赖 runc) - 其他基于 runc 的容器运行时(如 CRI-O)。 -- ### 二、**containerd 1.6.26 是否存在此漏洞?** #### 1. **直接结论** - **containerd 1.6.26 已修复漏洞**(官方修复版本为 **containerd >=1.6.18**)。 - 但需注意:containerd 的修复依赖于其捆绑的 **runc 版本是否升级到 >=1.1.12**。 #### 2. **验证步骤** - **步骤 1:检查 containerd 版本** 通过命令确认 containerd 版本: ```bash containerd --version # 输出示例:containerd containerd.io 1.6.26 ``` 若版本 >=1.6.18,则 containerd 自身已集成修复- **步骤 2:确认 runc 版本** containerd 默认会捆绑特定版本的 runc,需进一步检查实际使用的 runc 版本: ```bash # 查看 runc 路径(通常位于 /usr/bin/runc 或 containerd 安装目录中) which runc # 检查 runc 版本 runc --version # 输出示例:runc version 1.1.12 ``` **关键条件**:runc >=1.1.12 才视为安全。 #### 3. **可能的风险场景** - 若 containerd 升级到 1.6.26,但 runc 未同步更新(例如手动安装旧版 runc),漏洞仍存在。 - 某些云厂商或发行版的 containerd 可能自定义打包 runc,需确认其补丁策略。 --- ### 三、**K8S 环境修复建议** #### 1. **升级 containerd 和 runc** - **官方推荐方案**: - 升级 containerd 到最新稳定版(>=1.6.18),并确保其捆绑的 runc >=1.1.12。 - 若 runc 为独立安装,需单独升级: ```bash # 以 Ubuntu 为例 sudo apt-get update && sudo apt-get install runc ``` - **注意**:升级后重启 containerd 服务(避免影响运行中的容器): ```bash systemctl restart containerd ``` #### 2. **K8S 节点滚动更新** - 使用 K8S 的 **节点滚动升级** 策略,逐步替换所有 Worker 节点的 containerd 和 runc。 - 工具参考: - **kubeadm**: 升级节点时自动处理容器运行时。 - **Cluster API**: 自动化基础设施编排。 #### 3. **漏洞临时缓解措施**(若无法立即升级) - **限制容器权限**: - 在 Pod 的 `securityContext` 中禁用高危配置: ```yaml securityContext: privileged: false capabilities: drop: ["ALL"] readOnlyRootFilesystem: true ``` - 禁止挂载敏感宿主机目录(如 `/proc`、`/sys`)。 - **启用 Seccomp/AppArmor**:限制容器系统调用。 - **审计容器镜像**:确保不包含恶意构建步骤。 --- ### 四、**检测与验证** #### 1. **漏洞扫描工具** - **trivy**:扫描集群节点和镜像的 CVE 信息: ```bash trivy i --security-checks vuln containerd://1.6.26 trivy fs --security-checks vuln / ``` - **kube-hunter**:模拟攻击检测 K8S 集群风险。 #### 2. **PoC 验证** - 使用公开的漏洞验证脚本(需在测试环境执行): ```bash docker run --rm -it --security-opt "seccomp=unconfined" cve-21626-poc ``` - 若成功读取宿主机文件(如 `/etc/passwd`),则存在漏洞--- ### 五、总结 - **containerd 1.6.26 官方已修复 CVE-21626**,但需确认其实际使用的 runc 版本 >=1.1.12。 - **修复优先级**:高(容器逃逸可直接威胁宿主机)。 - **建议行动**: 1. 升级 containerd 和 runc 至安全版本。 2. 扫描集群节点和容器镜像,排查潜在攻击痕迹。 3. 加固容器安全配置(最小权限原则)。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼Linux运维

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值