Vulnerabilidad Dirty Frag en EKS: escalada a root desde un contenedor cuando falta seccomp

Dirty Frag (CVE-2026-43284) es un tipo de vulnerabilidad que, combinada con una postura permisiva a nivel de runtime (especialmente ausencia de perfiles seccomp efectivos), puede convertir un compromiso “limitado” dentro de un contenedor en una escalada a root en el nodo. En AWS EKS esto es crítico porque el nodo es el punto de concentración: credenciales de kubelet, volúmenes montados, logs, y el tránsito de red del cluster pasan o se observan desde ahí.

El problema práctico no es solo el CVE; es la cadena: un contenedor expuesto (RCE), capacidad de ejecutar syscalls peligrosas, y un kernel vulnerable. En equipos corporativos, he visto que el fallo se materializa cuando se prioriza “compatibilidad” (pods que funcionan con seccomp=unconfined) sobre guardrails, y se asume que el aislamiento del contenedor es suficiente. No lo es si el nodo cae.

Superficie de ataque real en EKS: del pod a root en el nodo

En EKS, un atacante suele empezar donde más duele: un microservicio con dependencias viejas, una imagen con herramientas de depuración incluidas o un endpoint interno expuesto por error. Con un RCE dentro del contenedor, el siguiente paso es buscar “salidas” del sandbox: syscalls, capacidades Linux, montajes, y cualquier cosa que conecte con el host.

Dirty Frag encaja justo en esa fase: si el kernel del nodo es vulnerable y el contenedor puede invocar ciertas syscalls sin restricciones, el atacante puede apuntar a una escalada local. En empresa, el impacto no se limita a “tomaron un nodo”: normalmente significa acceso a secretos en disco o en memoria, suplantación de identidad de kubelet, y potencial movimiento lateral (por ejemplo, leer tokens de service accounts de pods vecinos si existen montajes o rutas accesibles).

Un patrón que aparece en incidentes es que el equipo de plataforma endurece RBAC y NetworkPolicies, pero deja el runtime con defaults permisivos. Cuando el runtime deja ejecutar syscalls de alto riesgo, el atacante no necesita permisos Kubernetes elevados: le basta con ejecutar código dentro de un pod ya comprometido.

Escenario de abuso: un contenedor comprometido explota Dirty Frag cuando seccomp no corta syscalls

El laboratorio típico (y demasiado parecido a producción) es: pod comprometido → ejecución de exploit local → privilegios root en el host → persistencia o robo de credenciales. El punto operativo es que seccomp es uno de los controles que más directamente reduce la probabilidad de explotación práctica, porque limita syscalls que muchos exploits necesitan para manipular memoria, espacios de nombres o interfaces del kernel.

En EKS, es frecuente encontrar workloads con privileged: true “porque el driver lo pedía”, o con allowPrivilegeEscalation: true por herencia de charts antiguos. Si además seccompProfile está ausente o se usa Unconfined, el contenedor queda con una paleta de syscalls demasiado amplia. Con un kernel vulnerable, Dirty Frag deja de ser “teórico” y se convierte en un camino razonable a root.

Consecuencia real en empresa: el atacante que obtiene root en el nodo puede observar tráfico, manipular binarios del host (si consigue persistencia), acceder a credenciales de agentes (logging, monitoring) y, en algunos casos, alterar el comportamiento de kubelet. La limpieza posterior no es “borrar un pod”; suele implicar rotar credenciales, drenar y reciclar nodos, y revisar integridad de AMIs o imágenes del node group.

Señales tempranas y evidencias: qué mirar antes de que el nodo caiga

Los equipos que detectan pronto suelen correlacionar señales del plano de Kubernetes con telemetría del host. Si el atacante está intentando una escalada tipo Dirty Frag, verás comportamiento anómalo: procesos inesperados dentro del contenedor, picos de syscalls, o intentos repetidos que fallan hasta que “acierta” con el exploit.

En la práctica, lo que resulta accionable es definir “líneas rojas” por workload y alertar por desviación. Dos fuentes útiles suelen ser: auditoría de Kubernetes (quién crea pods con políticas permisivas) y eventos del runtime (syscalls bloqueadas o no bloqueadas, según el modo). Donde no hay seccomp, no habrá “bloqueos” que te alerten; solo verás síntomas tardíos, como inestabilidad del nodo o comportamientos extraños en kubelet.

  • Creación de pods con postura permisiva: si aparecen despliegues con securityContext relajado (privileged, capabilities extra, seccomp unconfined), es una señal de que un atacante o un pipeline comprometido está intentando abrir camino.

En entornos corporativos, esto se ve cuando un atacante consigue acceso a un namespace con permisos de despliegue (por ejemplo, credenciales de CI filtradas) y publica un pod “herramienta” para explotación. Si no tienes políticas de admisión, ese pod entra sin fricción.

  • Comportamiento atípico en nodos: reinicios, picos de CPU en procesos del runtime, mensajes del kernel, y drift de configuración del nodo. No confíes en “está healthy en el ASG”: un nodo puede estar “vivo” y ya comprometido.

Lo que marca la diferencia es tener observabilidad que permita aislar por nodo y por pod. En un incidente real, el MTTR baja drásticamente cuando puedes responder: “qué pod empezó, en qué nodo, con qué securityContext, y qué cambió antes de la degradación”.

Cómo hacerlo en la práctica: aplicar seccomp en EKS y forzar el estándar sin romper producción

El objetivo operativo es doble: aplicar perfiles seccomp y evitar excepciones silenciosas. En Kubernetes moderno, lo más práctico suele ser establecer RuntimeDefault en pods y containers, y bloquear Unconfined salvo excepciones justificadas y revisadas.

Ejemplo de configuración recomendable a nivel de Pod/Container (ajústalo a tu baseline y testing):

<!-- ejemplo YAML -->
apiVersion: v1
kind: Pod
metadata:
name: ejemplo
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: tu-imagen
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]

En empresa, el reto no es escribir el YAML; es migrar sin romper workloads “especiales” (observabilidad, agentes, storage, service meshes). La táctica que funciona es iterar por dominios: empezar por workloads stateless propios, medir bloqueos/errores, y después extender a componentes críticos. Si aparece un componente que requiere syscalls concretas, se documenta la excepción, se acota por namespace/labels, y se revisa con caducidad (no excepciones eternas).

Para que esto no dependa de disciplina humana, necesitas enforcement. En EKS, lo habitual es usar políticas de admisión (por ejemplo, Validating Admission Policies / admission controllers según tu versión y estrategia) para impedir que entren pods con seccomp deshabilitado. El resultado esperado es que el equipo de desarrollo reciba un error claro en el despliegue, en vez de enterarte en un postmortem.

  • Validar en clúster: revisa qué está corriendo realmente, no solo lo que “debería”. Usa kubectl get pod -A -o json y verifica spec.securityContext.seccompProfile y container.securityContext en workloads críticos.

En incidentes, es común descubrir que un chart sobreescribe el securityContext en el container, o que un initContainer queda sin seccomp. La validación debe cubrir initContainers y sidecars, no solo el container principal.

  • Validar en AWS/EKS: comprueba que los node groups están en una versión/AMI con el kernel parcheado o mitigado según tu proceso de hardening, y que el ciclo de actualización está funcionando (nodos nuevos sustituyen a los antiguos).

A nivel operacional, esto se traduce en: controlar el “drift” de AMIs, no permitir nodos longevos, y drenar/reciclar ante alertas. Dirty Frag es especialmente peligroso cuando convive con nodos sin rotación durante meses.

Recomendaciones para entornos corporativos

Dirty Frag en EKS se vuelve una ruta real a root cuando coinciden tres condiciones: contenedor comprometido, kernel vulnerable en el nodo y ausencia de restricciones efectivas como seccomp. En operación, la forma de reducir riesgo no es “confiar en el cluster”, sino cortar la cadena con controles que fallan cerrados.

La prioridad práctica es estandarizar seccomp: RuntimeDefault (y evitar Unconfined), acompañarlo con allowPrivilegeEscalation: false y reducción de capabilities, y asegurarse de que el enforcement impide excepciones no aprobadas. En paralelo, mantener node groups con rotación y actualizaciones al día reduce la ventana en la que un exploit de kernel puede funcionar.

Por último, la detección temprana depende de visibilidad sobre securityContext y cambios de despliegue. Si no puedes responder rápidamente qué pods corren sin seccomp o con escalación permitida, el problema no es solo Dirty Frag: es que tu plataforma permite que un compromiso de aplicación se convierta en compromiso de infraestructura.


¿Te interesa la seguridad en Cloud?

Comparto análisis técnicos, laboratorios prácticos y experiencias reales sobre Cloud Security.

Política de privacidad