Aikido

Una Guía de Vulnerabilidades de Escalada de Privilegios en Contenedores

Divine OdazieDivine Odazie
|
#
#

Una Guía de Vulnerabilidades de Escalada de Privilegios en Contenedores

Una de las muchas promesas de los contenedores es el aislamiento.

Mediante el uso cuidadoso de los namespaces y cgroups de Linux, los contenedores crean un sandbox donde se pueden ejecutar procesos de forma independiente. Esto, combinado con una excelente experiencia de desarrollador, hizo que los contenedores ganaran popularidad tanto entre ingenieros como entre profesionales de la seguridad. 

¿Pero es eso realmente suficiente?

¿Y puede asegurar que sus cargas de trabajo están a salvo en caso de que una de ellas se vea comprometida?

Pues bien, en esta publicación, abordaremos el sueño de todo atacante y la pesadilla de los administradores de sistemas, explicándole cómo y por qué sucede, y las formas de prevenirlo antes de que acabe en la portada de Hacker News. Para más información sobre vulnerabilidades de seguridad de contenedores Docker, consulte: Las 9 principales vulnerabilidades de seguridad de contenedores Docker.

Aislamiento de Contenedores y sus Brechas de Seguridad

Un detalle clave que a menudo se pasa por alto con los contenedores es que todos comparten el mismo host. Esto significa que cada contenedor es tan seguro como el siguiente. Si el host o un solo contenedor se ve comprometido, podría significar un desastre para su infraestructura.
Esto no significa que deba desechar los contenedores por completo. No. El objetivo aquí es entender la letra pequeña.

El aislamiento comienza a romperse cuando los atacantes encuentran una forma de escalar privilegios. La escalada de privilegios es uno de los movimientos más emocionantes y desafiantes en los ataques de seguridad ofensiva. Convierte un punto de apoyo con pocos privilegios en un compromiso total del sistema. 

Las vulnerabilidades de escalada de privilegios en contenedores hacen que eludir los límites de seguridad sea menos desafiante y mucho más gratificante, ya que un solo contenedor es suficiente para obtener acceso a un host. 

Esto no es solo teoría; la infame vulnerabilidad de runC de 2019 (CVE-2019-5736) permitió a los atacantes sobrescribir el binario runC del host y obtener acceso root al host.

Estos ataques no son algo pasajero, por lo que es posible que se encuentre con preguntas como esta:

Más recientemente, vulnerabilidades como CVE-2024-21626 y ataques sutiles basados en capas nos han demostrado que incluso los contenedores sin privilegios de root pueden volverse peligrosos cuando se hace un uso indebido de las capacidades de Linux, los montajes o las capas del sistema de archivos.

Por eso, basándonos en nuestra guía anterior sobre vulnerabilidades de Docker, exploraremos cómo funcionan estos ataques, los CVEs recientes que resaltan sus riesgos crecientes y cómo prevenirlos.

Vulnerabilidades Recientes de Escalada de Privilegios en Contenedores 

Aunque no todas las vulnerabilidades de contenedores conducen a la escalada de privilegios, las más peligrosas a menudo sí lo hacen. Algunas vulnerabilidades eluden el aislamiento de los contenedores y obtienen privilegios elevados como ninguna otra. 

A continuación, se presentan tres vulnerabilidades recientes de escalada de privilegios en contenedores. 

CVE-2024-21626: Escape del directorio de trabajo de runC

CVE-2024-21626 es una vulnerabilidad de escape de contenedor de alta gravedad que afecta al ampliamente utilizado runtime de contenedores, runC. La vulnerabilidad surge de un uso inseguro de la llamada prctl PR_SET_NO_NEW_PRIVS con execve, lo que permite a un atacante eludir el flag no_new_privs cuando el contenedor se inició con montajes o capacidades excesivamente permisivos. 

El flag no_new_privs es una de las mitigaciones principales contra la escalada de privilegios en la que muchos motores de contenedores confían para el sandboxing. 

La vulnerabilidad se introdujo en las versiones de runC a partir de la v1.1.11 y se corrigió en la v1.1.12.

CVE-2023-2640 y CVE-2023-32629 en el módulo OverlayFS del kernel de Ubuntu

OverlayFS es uno de los pilares fundamentales de los contenedores y Kubernetes. Superpone dos directorios (lowerdir y upperdir) en un único host Linux y los presenta como un único directorio, lo que proporciona un mejor rendimiento para los comandos Docker relacionados con capas, como docker build y docker commit.

CVE-2023-2640 y CVE-2023-32629 permiten a un actor malicioso utilizar un contenedor privilegiado no-root con un montaje de volumen para escalar privilegios. Esto es posible porque los montajes de volumen se tratan como discos separados y pueden utilizarse para crear OverlayFS, que existe fuera de la capa del contenedor. Esto permite a los atacantes eludir las restricciones estándar de los contenedores y manipular atributos de archivo extendidos en volúmenes montados, que luego se copian a la capa superior con las capacidades elevadas (como CAP_SETUID o CAP_SYS_ADMIN) intactas.

CVE-2022-0492

El 4 de marzo de 2022, investigadores de seguridad descubrieron una vulnerabilidad crítica en el cgroup_release_agent_write del kernel de Linux que tenía el potencial de permitir un Escape de contenedor y tomar el control de todo el nodo en el que se ejecuta el contenedor.

Los proveedores de la nube y las distribuciones de Linux actuaron rápidamente. Se emitieron parches y se publicaron avisos. Pero bajo la superficie, la complejidad persistía. A diferencia de otros softwares, el kernel de Linux carece de un esquema de versionado estandarizado entre las distribuciones. 

Lo que significó que aplicar estos parches y actualizar las imágenes base llevó meses. Durante ese tiempo, los entornos permanecieron susceptibles a posibles ataques.

Prevención de escaladas de privilegios en Docker y Docker Compose

La mejor manera de prevenir ataques de escalada de privilegios desde un contenedor Docker es configurar las aplicaciones de su contenedor para que se ejecuten como usuarios sin privilegios y luego asegurarse de que los contenedores no tengan acceso privilegiado.

En la práctica, para prevenir la escalada de privilegios en Docker, debe hacer lo siguiente:

Tiene dos opciones: ya sea en tiempo de ejecución o dentro de su configuración de Docker Compose. 

En tiempo de ejecución, utilice los siguientes flags:

docker run \     
--read-only \     
--security-opt=no-new-privileges \     
--network your-isolated-network \      
--cap-drop ALL     
--cap-add CHOWN \      
--pids-limit 99 \     
--user=your-user \ # su usuario no-root.    
...                 # OTRAS OPCIONES AQUÍ      
your-app:v1.0.1

Con Docker Compose, la configuración será:

services:        
webapp:           
image: your-app:v1.0.1        
read_only: true        
security_opt:           
- no-new-privileges:true        
networks:           
- your-isolated-network        
cap_drop:           
- ALL        
cap_add:           
- CHOWN                
# OTRAS OPCIONES AQUÍ          
...

Ejecución de contenedores que requieren acceso de usuario root

Hay casos (ejecución de utilidades del sistema, servicios heredados, etc.) en los que un contenedor podría requerir acceso root para ejecutarse. En estos casos, puede reasignar este usuario a un usuario con menos privilegios en el host de Docker.

La reasignación de un UID de contenedor garantiza que, aunque el contenedor crea que se está ejecutando como root, en realidad opera como un usuario sin privilegios desde la perspectiva del host, lo que reduce el riesgo de fuga de contenedor y compromiso del host. 

Puede consultar la documentación de Docker sobre reasignación de espacios de nombres de usuario para obtener pasos detallados y mejores prácticas.

Prevención de escalada de privilegios en Kubernetes

En Kubernetes, la mejor manera de prevenir la escalada de privilegios es durante la creación del contenedor, utilizando la configuración spec.containers.securityContext. Esto se debe a que, una vez que se crea un contenedor con privilegios excesivamente permisivos, no se puede actualizar en tiempo de ejecución y tendrá que eliminarlo y volver a crearlo. 

El siguiente securityContext protege el contenedor de la aplicación contra la escalada de privilegios, incluso con versiones de Linux del CVE-2022-0492 sin parchear, como se mencionó anteriormente. 

containers:  
- name: app    
image: myapp:bullseye-20230912    
securityContext:      
runAsUser: 1000 # Usar un ID de usuario no-root      
runAsGroup: 1000 # Usar un ID de grupo no-root      
runAsNonRoot: true # Forzar explícitamente la ejecución no-root      
allowPrivilegeEscalation: false # Evitar que el proceso obtenga más privilegios      
readOnlyRootFilesystem: true # Evitar escrituras en el sistema de archivos raíz      
capabilities:        
drop:          
- ALL # Eliminar todas las capacidades para minimizar la superficie de ataque        
add:          
- NET_BIND_SERVICE # Añadir solo las capacidades que la aplicación necesita      
seccompProfile:        
type: RuntimeDefault # Usar el perfil seccomp predeterminado del runtime del contenedor

Otra excelente forma de prevenir la escalada de privilegios en Kubernetes es evitar que los Pods sin un contexto de seguridad sean programados. Los controladores de admisión de Kubernetes permiten interceptar solicitudes al servidor API, por ejemplo, un despliegue, y validar que se cumplen ciertas condiciones antes de ser procesadas. 

Para casos de uso más avanzados, se puede escribir un controlador de admisión desde cero; sin embargo, soluciones de código abierto como Kyverno permiten escribir políticas a nivel de clúster que pueden parchear despliegues que no tienen un contexto de seguridad configurado. Esto suele tener el siguiente aspecto:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:  
name: add-default-securitycontext  
annotations:    
policies.kyverno.io/title: Añadir securityContext predeterminado    
policies.kyverno.io/category: Ejemplo    
policies.kyverno.io/subject: Pod    
policies.kyverno.io/minversion: 1.6.0    
policies.kyverno.io/description: >-      
Una entrada de securityContext de Pod define campos como el usuario y el grupo que deben usarse para ejecutar el Pod.
A veces, elegir valores predeterminados para los usuarios en lugar de bloquear es una alternativa mejor para no impedir      tales definiciones de Pod. Esta política mutará un Pod para establecer `runAsNonRoot`, `runAsUser`, `runAsGroup` y       `fsGroup` dentro del securityContext del Pod si aún no están configurados.
spec:  
rules:  
- name: add-default-securitycontext    
match:     
any:      
- resources:          
kinds:          
- Pod    
mutate:      
patchStrategicMerge:        
spec:          
securityContext:            
+(runAsNonRoot): true            
+(runAsUser): 1000            
+(runAsGroup): 3000            
+(fsGroup): 2000

El manifiesto anterior utiliza la definición de recurso personalizado (CRD) ClusterPolicy para parchear pods a través de mutate.PatchStrategicMerge y un contexto de seguridad con un usuario no root. 

Los Contenedores Seguros Se Construyen, No Se Asumen

Aunque los contenedores proporcionan aislamiento y una forma fiable de construir y ejecutar aplicaciones, la naturaleza cambiante de la seguridad de contenedores significa que no se puede depender únicamente de medidas preventivas. En su lugar, se debe utilizar una estrategia que permita responder rápidamente a los incidentes a medida que ocurren. 

Esa estrategia comienza con el escaneo proactivo.

Con Aikido, puede escanear automáticamente imágenes de contenedores para descubrir paquetes vulnerables, runtimes obsoletos o instrucciones Dockerfile arriesgadas antes de que lleguen a producción. Su escáner de dependencias de código abierto extiende esta protección al comprobar sus librerías en busca de CVEs explotables e incluso vulnerabilidades parcheadas silenciosamente que los atacantes podrían usar para obtener privilegios escalados.

Estos escaneos se refuerzan con comprobaciones de IaC y configuración que señalan configuraciones inseguras de Kubernetes o Docker, y con puertas de seguridad CI/CD que aplican políticas de mínimo privilegio a nivel de pipeline. Y como la prevención nunca puede ser perfecta, Aikido Zen añade protección en tiempo de ejecución para detectar y responder a comportamientos anómalos de contenedores en tiempo real.

4.7/5

Protege tu software ahora.

Empieza gratis
Sin tarjeta
Solicitar una demo
Sus datos no se compartirán · Acceso de solo lectura · No se requiere tarjeta de crédito

Asegúrate ahora.

Proteja su código, la nube y el entorno de ejecución en un único sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No se requiere tarjeta de crédito | Resultados del escaneo en 32 segundos.