Veamos cómo endurecer y asegurar Docker para el entorno de producción.

Aunque Docker ha hecho posible que los desarrolladores de software y los ingenieros DevOps construyan y desplieguen aplicaciones rápidamente, también viene con una gran superficie de ataque que los piratas cibernéticos pueden aprovechar.

Vamos a ver cómo asegurar un Docker en una plataforma Linux a partir de lo siguiente.

  • Defectos de configuración
  • Ejecución remota de código
  • Desbordamientos de búfer
  • Falsificación de imágenes, etc.

Haremos uso de las siguientes herramientas, como el servidor notarial de Docker para firmar imágenes y el banco de seguridad de Docker para comprobar el host, la configuración del demonio, etc.

Antes de proceder a la seguridad, vamos a tocar los fundamentos.

¿Qué es una tecnología de contenedores?

La tecnología de contenedores permite a los desarrolladores o ingenieros DevOps empaquetar una aplicación para que pueda ejecutarse con dependencias aisladas de otros procesos.

Existen varias tecnologías de contenedores en el mercado, como Apache Mesos, lxc y Docker. Aunque entran dentro de la categoría de tecnología de contenedores, funcionan de forma diferente.

Diferencia entre VM y VE

Un host de máquina virtual es totalmente diferente de un host de entorno virtual. En las máquinas virtuales, cada aplicación en contenedor viene con su propio conjunto de bibliotecas y sistema operativo mientras que las aplicaciones, por defecto, en un host de entorno virtual como lxc, y docker comparten el núcleo Linux.

¿Qué es Docker?

Docker es una tecnología de contenedores utilizada por millones para crear una aplicación web y desplegarla desde un entorno de pruebas a uno de producción.

Motor Docker

El motor Docker está formado por tres componentes.

  • Un Servidor: Este componente es un proceso de larga duración o demonio responsable de la gestión de imágenes y contenedores.
  • UNA API REST: Esta interfaz hace posible la comunicación entre el demonio Docker y la herramienta cliente Docker.
  • Herramienta cliente Docker: La herramienta cliente Docker hace uso del componente API REST para informar al demonio Docker del funcionamiento de una aplicación en contenedores.

Registro de confianza Docker

Docker Trusted Registry es una solución de almacenamiento de imágenes de Docker para el negocio de plataformas empresariales. Es diferente del docker hub. Mientras que el docker hub se aloja en la nube, el registro de confianza de Docker es una solución de almacenamiento local para la edición empresarial de Docker.

Docker Content Trust

Docker Content Trust ofrece la posibilidad de utilizar firmas de datos para las imágenes enviadas y recibidas desde y hacia registros remotos de Docker, como el docker hub.

Espacios de nombres Linux

Los espacios de nombres Linux son una característica del núcleo Linux que aísla una aplicación o proceso en contenedor que se ejecuta en un host de entorno virtual de otros procesos.

Grupos de Control Linux(Cgroups)

Los grupos de control Linux son una característica del núcleo Linux que le permite asignar recursos como tiempo de CPU, ancho de banda de red, memoria del sistema, etc. a los procesos activos en un host.

Capacidades

En Linux, existe una característica de seguridad en el subsistema del núcleo que puede configurarse o aplicarse para limitar el proceso privilegiado como un proceso ejecutado por un usuario con UID 1. Aunque los procesos o usuarios privilegiados pueden saltarse los permisos discrecionales de control de acceso, no pueden saltarse las reglas de capacidades.

Centrémonos ahora en la seguridad.

Seguridad del host Docker

En esta sección, veremos cómo asegurar el host donde reside Docker.

Escaneando el kernel Linux

Antes de alojar un Docker en una plataforma Linux, primero debe inspeccionar el kernel. Existen varias herramientas de código abierto como Lynis y OpenVAS que puede utilizar para escanear el kernel de Linux.

Copie o clone el proyecto Lynis desde Github utilizando el comando git clone.

git clone https://github.com/CISOfy/lynis.git

A continuación, utilice el siguiente comando para navegar hasta el directorio lynis y auditar el sistema Linux.

cd lynis; ./lynis auditar sistema

Endurezca el kernel de Linux

Después de haber escaneado el núcleo Linux en busca de vulnerabilidades basadas en el sistema, puede añadir otra capa extra de protección al núcleo mediante grsecurity. Proporciona características de seguridad como las siguientes

  • Prevención de la explotación del desbordamiento del búfer
  • prevención de vulnerabilidades de carrera en /tmp
  • restricciones de /proc que no filtran información sobre los propietarios de los procesos.
  • Prevención de la ejecución de código arbitrario en el núcleo, etc.

Inicialmente, puede descargar parches de forma gratuita desde grsecurity y aplicarlos a su núcleo actual. Pero ya no permite parches gratuitos.

Instale Docker en una VM

En lugar de instalar Docker directamente en un host Linux, puede añadir una capa extra de protección instalándolo dentro de una máquina virtual. Al hacerlo, incluso si hay un problema de vulnerabilidad con el kernel del host, no afectará a los contenedores Docker.

Proteger los privilegios de root

Por defecto, Docker requiere privilegios de root para crear y gestionar contenedores. El script malicioso puede aprovechar esta superficie de ataque para escalar a un superusuario en un host Linux y eventualmente acceder a archivos/carpetas sensibles, imágenes, certificados, etc.

Para evitarlo, podemos hacer uso del siguiente comando. Podemos decidir abandonar capacidades como setgid y setuid para evitar que otros programas o procesos cambien su GID por otro GID que pueda resultar en una escalada de privilegios. También puede consultar aquí la lista de definición de capacidades de Linux.

El comando que se muestra a continuación ejecuta el contenedor apache webserver y elimina las capacidades setgid y setuid mediante --cap-drop para evitar que el contenedor apache cambie su GID y UID por otro UID y GID.

GID y UID en este contexto se refieren a ID de grupo e ID de usuario respectivamente.

docker run -d --cap-drop SETGID --cap-drop SETUID apache

Usuario Docker

Aparte de evitar otros programas o procesos, también puede crear un usuario para gestionar operaciones docker como docker run en lugar de gestionarlo a través de un superusuario.

Puede añadir o crear un usuario docker mediante lo siguiente:

sudo groupadd docker

El comando anterior crea un grupo llamado docker

A continuación, cree un usuario mediante el siguiente comando:

sudo useradd mike

Por último, utilice el siguiente comando para añadir un usuario mike al grupo docker para administrar las operaciones de docker.

sudo usermod -aG docker mike

Administración de contenedores con Cgroups

En un entorno de producción, es posible que tenga más de un contenedor.

Si no tiene instalado cgroups en su host, puede utilizar el siguiente comando para instalarlo y luego consultar aquí (para Ubuntu) cómo configurarlo.

sudo apt-get install cgroup-bin cgroup-lite cgroup-tools cgroupfs-mount libcgroup1

Podemos asignar los contenedores a recursos de CPU limitados mediante --cpu-shares y --cpuset-cpus

El siguiente ejemplo de comando muestra que el proceso contenedor prodnginx se ejecuta sólo en el primer núcleo mediante --cpuset-cpus y se le asignan 20 CPU mediante --cpu-shares mientras que el proceso contenedor proxnginx se ejecuta en los dos primeros núcleos de CPU y también se le asignan 20 CPU.

docker run -d --name prodnginx --cpuset-cpus=0 --cpu-shares=20 nginx
docker run -d --name testnginx --cpuset-cpus=2 --cpu-shares=20 nginx

A continuación, escriba el comando docker stats para ver el uso de la CPU por los contenedores prodnginx y testnginx

CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
845bea7263fb prodnginx 57.69% 1.258MiB / 985.2MiB 0.13% 578B / 0B 1.33MB / 0B 
189ba15e8258 testnginx 55.85% 1.25MiB / 985.2MiB 0.13% 578b / 0B 1.33MB / 0B 

Es una buena idea definir CPU-shares para un host docker cuando tiene más de un contenedor ejecutándose en él.

Gestión de contenedores con espacios de nombres

Un espacio de nombres puede evitar que los contenedores se ejecuten como usuarios con privilegios, lo que puede ayudar a evitar ataques de escalada de privilegios.

Podemos habilitar el espacio de nombres en docker haciendo uso de los archivos /etc/subuid y /etc/subgid como se muestra a continuación.

  • cree un usuario utilizando el comando adduser
sudo adduser dockremap
  • Configure un subuid para el usuario dockremap
sudo sh -c 'echo dockremap:400000:65536 > /etc/subuid'
  • A continuación, configure un subgid para el usuario dockremap
sudo sh -c 'echo dockremap:400000:65536 > /etc/subgid'
  • Abra el archivo daemon.json y rellénelo con el siguiente contenido para asociar el atributo userns-remap al usuario dockremap
vi /etc/docker/daemon.json
{ 

 "userns-remap": "dockremap"

}
  • Pulse :wq para guardar y cerrar el archivo daemon.json y, por último, reinicie docker para habilitar los espacios de nombres en un host docker
sudo /etc/init.d/docker restart

Asegurar el demonio Docker

También es necesario configurar el demonio Docker para garantizar una comunicación segura entre el cliente Docker y el demonio Docker a través de TLS.

Utilice el siguiente comando para abrir el archivo daemon.j son y copie y pegue el siguiente contenido (sustituya la IP por la suya actual) como se muestra a continuación

vi daemon.json
{
  "debug": false
  "tls": true
  "tlscert": "/var/docker/server.pem",
  "tlskey": "/var/docker/serverkey.pem",
  "hosts": ["tcp://192.168.16.5:2376"]
}

Asegurar los componentes de Docker

Veamos cómo hacer uso de herramientas como CodeNotary y el servidor notarial para firmar imágenes con el fin de evitar la falsificación de imágenes. Además, también es necesario escanear las imágenes para asegurarse de que no están repletas de vulnerabilidades

Haremos uso del servidor notarial de Docker para firmar y verificar imágenes y utilizaremos Anchor Engine para escanear imágenes en busca de vulnerabilidades.

Verificar imágenes con el servidor notario

Antes de que podamos hacer uso del servidor Notary para firmar imágenes, necesitamos descargar e instalar docker-compose. Utilizaremos Docker Compose para configurar un servidor notario.

  • Ejecute el siguiente comando para descargar la última versión de Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  • Aplique permisos de ejecución a docker-compose como se muestra a continuación
sudo chmod 700 /usr/local/bin/docker-compose
  • Puede comprobar si ha instalado correctamente docker-compose mediante el siguiente comando
docker-compose --version
  • Ahora podemos instalar el servidor notario a través de docker-compose
git clone https://github.com/theupdateframework/notary.git
  • El comando anterior clona o copia el servidor notarial del repositorio notarial
  • Inicie el servidor notarial y el firmante mediante los siguientes comandos
docker-compose build
docker-compose up -d
  • A continuación, copie la configuración y los certificados de prueba en su directorio local del notario mediante el siguiente comando
mkdir -p ~/.notary && cp cmd/notary/config.json cmd/notary/root-ca.crt ~/.notary
  • Ahora ejecute el siguiente comando para conectar el servidor notary al cliente docker
export DOCKER_CONTENT_TRUST=1
export DOCKER_CONTENT_TRUST_SERVER=https://notaryserver:4443
  • Genere un par de claves de delegación mediante el siguiente comando
docker trust key generate mike --dir ~./docker/trust        
  • Ahora vamos a crear un objetivo nuevas claves en caso de que el repositorio no existe
docker trust signer add --key ~/.docker/trust/mike.pub mike mikedem0/whalesay
  • A continuación, puede firmar su imagen docker utilizando el comando docker trust sign. Necesita extraer la imagen docker del docker hub y re-etiquetarla utilizando el comando docker pull y docker tag respectivamente.
docker trust sign mikedem0/nginx:latest

También puede escanear las imágenes docker en busca de vulnerabilidades y fallos de configuración. Puede consultar aquí cómo utilizar Anchor Engine para escanear en busca de vulnerabilidades y Docker Bench Security para buscar fallos de configuración.

Espero que lo anterior le dé una idea sobre la seguridad Docker para el entorno de producción. Es posible que también desee echar un vistazo a este curso Udemy sobre la piratería y la seguridad de los contenedores Docker.