Docker Security
Last updated
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Utiliza Trickest para construir y automatizar flujos de trabajo fácilmente con las herramientas comunitarias más avanzadas del mundo. ¡Accede hoy mismo:
El motor de Docker utiliza los Namespaces y Cgroups del kernel de Linux para aislar contenedores, ofreciendo una capa básica de seguridad. La protección adicional se logra mediante la reducción de capacidades, Seccomp y SELinux/AppArmor, mejorando el aislamiento de los contenedores. Un plugin de autenticación puede restringir aún más las acciones de los usuarios.
El motor de Docker puede ser accedido localmente a través de un socket Unix o de forma remota utilizando HTTP. Para el acceso remoto, es esencial emplear HTTPS y TLS para garantizar confidencialidad, integridad y autenticación.
El motor de Docker, por defecto, escucha en el socket Unix en unix:///var/run/docker.sock
. En sistemas Ubuntu, las opciones de inicio de Docker se definen en /etc/default/docker
. Para habilitar el acceso remoto a la API y al cliente de Docker, expone el demonio de Docker sobre un socket HTTP añadiendo la siguiente configuración:
Sin embargo, exponer el demonio de Docker a través de HTTP no es recomendado debido a preocupaciones de seguridad. Es aconsejable asegurar las conexiones utilizando HTTPS. Hay dos enfoques principales para asegurar la conexión:
El cliente verifica la identidad del servidor.
Tanto el cliente como el servidor se autentican mutuamente.
Se utilizan certificados para confirmar la identidad de un servidor. Para ejemplos detallados de ambos métodos, consulta esta guía.
Las imágenes de contenedores pueden almacenarse en repositorios privados o públicos. Docker ofrece varias opciones de almacenamiento para imágenes de contenedores:
Docker Hub: Un servicio de registro público de Docker.
Docker Registry: Un proyecto de código abierto que permite a los usuarios alojar su propio registro.
Docker Trusted Registry: Oferta de registro comercial de Docker, con autenticación de usuario basada en roles e integración con servicios de directorio LDAP.
Los contenedores pueden tener vulnerabilidades de seguridad ya sea debido a la imagen base o al software instalado encima de la imagen base. Docker está trabajando en un proyecto llamado Nautilus que realiza un escaneo de seguridad de los Contenedores y lista las vulnerabilidades. Nautilus funciona comparando cada capa de imagen de Contenedor con un repositorio de vulnerabilidades para identificar agujeros de seguridad.
Para más información lee esto.
docker scan
El comando docker scan
te permite escanear imágenes de Docker existentes utilizando el nombre de la imagen o el ID. Por ejemplo, ejecuta el siguiente comando para escanear la imagen hello-world:
La firma de imágenes de Docker garantiza la seguridad y la integridad de las imágenes utilizadas en contenedores. Aquí tienes una explicación resumida:
Para activar la confianza en el contenido de Docker, establece export DOCKER_CONTENT_TRUST=1
. Esta función está desactivada de forma predeterminada en Docker versión 1.10 y posteriores.
Con esta función habilitada, solo se pueden descargar imágenes firmadas. La carga inicial de la imagen requiere establecer frases de contraseña para las claves raíz y de etiquetado, con Docker también admitiendo Yubikey para una seguridad mejorada. Puedes encontrar más detalles aquí.
Intentar descargar una imagen no firmada con la confianza en el contenido habilitada resulta en un error de "No hay datos de confianza para la última versión".
Para las cargas de imágenes posteriores a la primera, Docker solicita la frase de contraseña de la clave del repositorio para firmar la imagen.
Para hacer una copia de seguridad de tus claves privadas, utiliza el comando:
Cuando se cambia de hosts de Docker, es necesario mover las claves de root y del repositorio para mantener las operaciones.
Utiliza Trickest para construir fácilmente y automatizar flujos de trabajo impulsados por las herramientas comunitarias más avanzadas del mundo. Obtén acceso hoy:
Namespaces son una característica del kernel de Linux que particiona los recursos del kernel de tal manera que un conjunto de procesos ve un conjunto de recursos mientras que otro conjunto de procesos ve un conjunto diferente de recursos. La característica funciona teniendo el mismo espacio de nombres para un conjunto de recursos y procesos, pero esos espacios de nombres se refieren a recursos distintos. Los recursos pueden existir en múltiples espacios.
Docker hace uso de los siguientes Namespaces del kernel de Linux para lograr el aislamiento de Contenedores:
espacio de nombres pid
espacio de nombres de montaje
espacio de nombres de red
espacio de nombres ipc
espacio de nombres UTS
Para más información sobre los namespaces consulta la siguiente página:
La característica del kernel de Linux cgroups proporciona la capacidad de restringir recursos como cpu, memoria, io, ancho de banda de red entre un conjunto de procesos. Docker permite crear Contenedores utilizando la característica cgroup que permite el control de recursos para el Contenedor específico. A continuación se muestra un Contenedor creado con la memoria del espacio de usuario limitada a 500m, la memoria del kernel limitada a 50m, la cuota de CPU a 512, el peso de blkioweight a 400. La cuota de CPU es una proporción que controla el uso de CPU del Contenedor. Tiene un valor predeterminado de 1024 y un rango entre 0 y 1024. Si tres Contenedores tienen la misma cuota de CPU de 1024, cada Contenedor puede utilizar hasta el 33% de la CPU en caso de contención de recursos de CPU. blkio-weight es una proporción que controla la E/S del Contenedor. Tiene un valor predeterminado de 500 y un rango entre 10 y 1000.
Para obtener el cgroup de un contenedor puedes hacer lo siguiente:
Para obtener más información, consulta:
Las capacidades permiten un control más preciso de las capacidades que se pueden permitir para el usuario root. Docker utiliza la característica de capacidades del kernel de Linux para limitar las operaciones que se pueden realizar dentro de un contenedor independientemente del tipo de usuario.
Cuando se ejecuta un contenedor de Docker, el proceso elimina las capacidades sensibles que el proceso podría usar para escapar del aislamiento. Esto intenta asegurar que el proceso no pueda realizar acciones sensibles y escapar:
Esta es una característica de seguridad que permite a Docker limitar las syscalls que se pueden utilizar dentro del contenedor:
AppArmor es una mejora del kernel para confinar contenedores a un conjunto limitado de recursos con perfiles por programa.:
Sistema de Etiquetado: SELinux asigna una etiqueta única a cada proceso y objeto del sistema de archivos.
Aplicación de Políticas: Hace cumplir políticas de seguridad que definen qué acciones puede realizar una etiqueta de proceso en otras etiquetas dentro del sistema.
Etiquetas de Procesos de Contenedores: Cuando los motores de contenedores inician procesos de contenedores, generalmente se les asigna una etiqueta SELinux confinada, comúnmente container_t
.
Etiquetado de Archivos dentro de los Contenedores: Los archivos dentro del contenedor suelen estar etiquetados como container_file_t
.
Reglas de Política: La política de SELinux garantiza principalmente que los procesos con la etiqueta container_t
solo puedan interactuar (leer, escribir, ejecutar) con archivos etiquetados como container_file_t
.
Este mecanismo garantiza que incluso si un proceso dentro de un contenedor se ve comprometido, está confinado para interactuar solo con objetos que tengan las etiquetas correspondientes, limitando significativamente el daño potencial de tales compromisos.
En Docker, un complemento de autorización desempeña un papel crucial en la seguridad al decidir si permitir o bloquear las solicitudes al demonio de Docker. Esta decisión se toma examinando dos contextos clave:
Contexto de Autenticación: Incluye información completa sobre el usuario, como quiénes son y cómo se han autenticado.
Contexto de Comando: Comprende todos los datos pertinentes relacionados con la solicitud que se está realizando.
Estos contextos ayudan a garantizar que solo se procesen solicitudes legítimas de usuarios autenticados, mejorando la seguridad de las operaciones de Docker.
Si no se limitan adecuadamente los recursos que un contenedor puede utilizar, un contenedor comprometido podría realizar un ataque de denegación de servicio (DoS) en el host donde se está ejecutando.
DoS de CPU
Denegación de Servicio de Ancho de Banda
En la siguiente página puedes aprender qué implica la bandera --privileged
:
Si estás ejecutando un contenedor donde un atacante logra obtener acceso como un usuario de baja privilegios. Si tienes un binario suid mal configurado, el atacante podría abusar de él y escalar privilegios dentro del contenedor. Lo cual podría permitirle escapar de él.
Ejecutar el contenedor con la opción no-new-privileges
habilitada evitará este tipo de escalada de privilegios.
Para obtener más opciones de --security-opt
consulta: https://docs.docker.com/engine/reference/run/#security-configuration
Es crucial evitar incrustar secretos directamente en las imágenes de Docker o utilizar variables de entorno, ya que estos métodos exponen tu información sensible a cualquier persona con acceso al contenedor a través de comandos como docker inspect
o exec
.
Los volúmenes de Docker son una alternativa más segura, recomendada para acceder a información sensible. Pueden ser utilizados como un sistema de archivos temporal en memoria, mitigando los riesgos asociados con docker inspect
y el registro. Sin embargo, los usuarios root y aquellos con acceso exec
al contenedor aún podrían acceder a los secretos.
Secretos de Docker ofrecen un método aún más seguro para manejar información sensible. Para casos que requieran secretos durante la fase de construcción de la imagen, BuildKit presenta una solución eficiente con soporte para secretos en tiempo de construcción, mejorando la velocidad de construcción y proporcionando características adicionales.
Para aprovechar BuildKit, se puede activar de tres maneras:
A través de una variable de entorno: export DOCKER_BUILDKIT=1
Prefijando comandos: DOCKER_BUILDKIT=1 docker build .
Habilitándolo de forma predeterminada en la configuración de Docker: { "features": { "buildkit": true } }
, seguido de un reinicio de Docker.
BuildKit permite el uso de secretos en tiempo de construcción con la opción --secret
, asegurando que estos secretos no se incluyan en la caché de construcción de la imagen o en la imagen final, utilizando un comando como:
Para los secretos necesarios en un contenedor en ejecución, Docker Compose y Kubernetes ofrecen soluciones sólidas. Docker Compose utiliza una clave secrets
en la definición del servicio para especificar archivos secretos, como se muestra en un ejemplo de docker-compose.yml
:
Esta configuración permite el uso de secretos al iniciar servicios con Docker Compose.
En entornos de Kubernetes, los secretos son compatibles de forma nativa y se pueden gestionar aún más con herramientas como Helm-Secrets. Los Controles de Acceso Basados en Roles (RBAC) de Kubernetes mejoran la seguridad en la gestión de secretos, similar a Docker Enterprise.
gVisor es un núcleo de aplicación, escrito en Go, que implementa una parte sustancial de la superficie del sistema Linux. Incluye un tiempo de ejecución de Open Container Initiative (OCI) llamado runsc
que proporciona un límite de aislamiento entre la aplicación y el núcleo del host. El tiempo de ejecución runsc
se integra con Docker y Kubernetes, lo que facilita la ejecución de contenedores en sandbox.
Kata Containers es una comunidad de código abierto que trabaja para construir un tiempo de ejecución de contenedores seguro con máquinas virtuales ligeras que se sienten y se comportan como contenedores, pero proporcionan una mayor aislamiento de carga de trabajo utilizando tecnología de virtualización de hardware como una segunda capa de defensa.
No utilices la bandera --privileged
ni montes un socket de Docker dentro del contenedor. El socket de Docker permite generar contenedores, por lo que es una forma sencilla de tomar el control total del host, por ejemplo, ejecutando otro contenedor con la bandera --privileged
.
No ejecutes como root dentro del contenedor. Utiliza un usuario diferente y espacios de nombres de usuario. El root en el contenedor es el mismo que en el host a menos que se remapee con espacios de nombres de usuario. Está solo ligeramente restringido por, principalmente, espacios de nombres de Linux, capacidades y cgroups.
Elimina todas las capacidades (--cap-drop=all
) y habilita solo las necesarias (--cap-add=...
). Muchas cargas de trabajo no necesitan capacidades y agregarlas aumenta el alcance de un posible ataque.
Utiliza la opción de seguridad “no-new-privileges” para evitar que los procesos obtengan más privilegios, por ejemplo, a través de binarios suid.
Limita los recursos disponibles para el contenedor. Los límites de recursos pueden proteger la máquina de ataques de denegación de servicio.
Utiliza imágenes oficiales de Docker y exige firmas o construye las tuyas basadas en ellas. No heredes ni uses imágenes con puertas traseras. También guarda las claves raíz, frases de contraseña en un lugar seguro. Docker tiene planes para gestionar claves con UCP.
Reconstruye regularmente tus imágenes para aplicar parches de seguridad al host e imágenes.
Gestiona tus secretos sabiamente para que sea difícil para el atacante acceder a ellos.
Si expones el daemon de Docker, utiliza HTTPS con autenticación de cliente y servidor.
En tu Dockerfile, prefiere COPY en lugar de ADD. ADD extrae automáticamente archivos comprimidos y puede copiar archivos desde URL. COPY no tiene estas capacidades. Siempre que sea posible, evita usar ADD para no ser susceptible a ataques a través de URL remotas y archivos Zip.
Ten contenedores separados para cada microservicio.
No incluyas ssh dentro del contenedor, "docker exec" se puede usar para ssh al contenedor.
Utiliza imágenes de contenedor más pequeñas
Si estás dentro de un contenedor de Docker o tienes acceso a un usuario en el grupo de Docker, podrías intentar escapar y escalar privilegios:
Si tienes acceso al socket de Docker o tienes acceso a un usuario en el grupo de Docker pero tus acciones están siendo limitadas por un plugin de autenticación de Docker, verifica si puedes burlarlo:
La herramienta docker-bench-security es un script que verifica docenas de prácticas recomendadas comunes sobre la implementación de contenedores Docker en producción. Las pruebas son todas automatizadas y se basan en el CIS Docker Benchmark v1.3.1. Debes ejecutar la herramienta desde el host que ejecuta Docker o desde un contenedor con suficientes privilegios. Descubre cómo ejecutarlo en el README: https://github.com/docker/docker-bench-security.
Utiliza Trickest para construir y automatizar flujos de trabajo fácilmente con las herramientas comunitarias más avanzadas del mundo. Accede hoy mismo:
Aprende y practica Hacking en AWS: Entrenamiento HackTricks AWS Red Team Expert (ARTE) Aprende y practica Hacking en GCP: Entrenamiento HackTricks GCP Red Team Expert (GRTE)