Una grave falla de seguridad en runC puede permitir la escalada de privilegios a root en Docker y Kubernetes
13 de febrero de 2019
0 minutos de lecturaAdam Iwaniuk y Borys Popławski descubrieron una falla de seguridad en el software de código abierto runC que se divulgó el 11 de febrero de 2019 y se describió en CVE-2019-5736.
La vulnerabilidad, que afecta a varios motores de contenedores como Docker y Kubernetes, se encuentra en un componente clave de estos motores y permite que los contenedores salgan de su entorno aislado y accedan al servidor host donde se ejecutan. Así, pueden acceder también a otros contenedores y obtener privilegios de root en el host.
Este problema de seguridad se suma a una vulnerabilidad crítica reportada el 3 de diciembre de 2018, que encontró un componente de la API de Kubernetes vulnerable a ataques que permiten ejecutar comandos arbitrarios en contenedores en ejecución.
William Bowling compartió en Twitter un video que muestra el ataque de prueba de concepto en acción. El binario runC del servidor host se modifica desde un contenedor en ejecución con una versión que contiene una puerta trasera:
Hoy, Iwaniuk y Popławski publicaron una entrada de blog que detalla el ataque a runC y describe qué los inspiró a investigar y descubrir la vulnerabilidad.
La vulnerabilidad
¿Cómo es posible esta vulnerabilidad? Christian Brauner escribió sobre la importancia de entender las diferencias semánticas entre los contenedores privilegiados y los no privilegiados:
Lo que realmente queremos decir con un contenedor privilegiado es que la semántica del ID 0 es la misma dentro y fuera del contenedor, en igualdad de condiciones. Digo «en igualdad de condiciones» porque el uso de LSM, seccomp o cualquier otro mecanismo de seguridad no cambia el significado del ID 0 dentro y fuera del contenedor. Por ejemplo, una salida del contenedor provocada por un error en la implementación del entorno de ejecución te dará acceso de root al host.
Un contenedor no privilegiado es aquel en el que la semántica del ID 0 dentro del contenedor es distinta de la del ID 0 fuera de él. Por ejemplo, una salida del contenedor provocada por un error en la implementación del entorno de ejecución no te dará acceso de root al host de forma predeterminada. Esto solo debería ser posible si hay un error en la implementación del espacio de nombres de usuario del kernel.
La gravedad de esta vulnerabilidad y su alcance se deben a que los contenedores de Docker se ejecutan como contenedores privilegiados de forma predeterminada, además de a la naturaleza del uso del binario de línea de comandos runC.
Comienza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag con nuestro taller virtual 101 a pedido.
Como explica Brauner, las implementaciones de tecnología de contenedores, como Docker, ejecutan el binario runC cada vez que se indica un comando para un contenedor; después, el proceso runC termina. Por eso, un contenedor malicioso puede modificar el binario runC, y todas las instrucciones posteriores para los contenedores ejecutarán efectivamente el binario runC modificado.
Esto difiere considerablemente del funcionamiento de LXC, donde un proceso similar no termina después de ejecutar las instrucciones del contenedor:
LXC no es vulnerable a ataques a través de imágenes maliciosas, ya que el proceso monitor (único para cada contenedor) nunca se cierra durante el ciclo de vida del contenedor. Como el kernel no permite modificar los binarios en ejecución, el atacante no puede dañarlo. Cuando se apaga o se detiene el contenedor, la tarea maliciosa termina antes de poder causar daño. El monitor solo se cierra cuando termina el último proceso que se ejecuta dentro del contenedor. Por eso, si ejecutas contenedores OCI privilegiados mediante nuestra plantilla OCI con LXC, las imágenes maliciosas no representan un riesgo. Solo sigue siendo aplicable el vector que aprovecha el binario de conexión.
Esta vulnerabilidad también nos recuerda el principio de seguridad de privilegios mínimos y la práctica recomendada de asegurarse de que el eslabón más débil no permita una escalada de privilegios ni la explotación de otras vulnerabilidades.
Problemas de seguridad y divulgación responsable
La premisa fundamental de la tecnología de contenedores es aislar las distintas aplicaciones y servicios, por lo que es inevitable que se enciendan las alarmas cuando esto no se cumple.
Los ataques a la cadena de suministro de software no son nuevos en el mundo de los contenedores y también han aparecido en titulares por las bibliotecas de aplicaciones. Un artículo publicado en Threatpost en 2018 informó que una investigación de Kromtech Security Center encontró que se estaban usando activamente más de 17 contenedores maliciosos para actividades ilegales de criptominería. Las imágenes maliciosas se alojaron en Docker Hub, el registro público oficial de imágenes de Docker, y luego se eliminaron.
En una actualización sobre la vulnerabilidad de runC, Aleksa Sarai, responsable del mantenimiento de runC e ingeniero sénior de software en SUSE Linux, compartió ayer que otra tecnología de contenedores de Linux llamada LXC también es vulnerable al CVE mencionado, aunque mediante un vector de ataque diferente.
También mencionó que el código de explotación se hará público el 18 de febrero para comprobar y verificar que la vulnerabilidad de seguridad se haya corregido correctamente, e instó a los usuarios a aplicar los parches de manera responsable.
Si aún no probaste Snyk, considera usar nuestra CLI para ejecutar pruebas localmente o conectar tus repositorios de código fuente y automatizar el análisis y la corrección. Si ya usas Snyk, debes saber que registramos esta vulnerabilidad en la base de datos.
Nos alegra saber que la Open Container Initiative (OCI) agregó un archivo SECURITY.md a su registro para ofrecer a los investigadores pautas de divulgación responsable sobre problemas de seguridad. Ya habíamos recomendado esta medida, junto con otras pautas para la gestión segura del código fuente que puedes consultar en nuestras prácticas recomendadas de seguridad de GitHub.
Conclusiones
Evita ejecutar imágenes base de contenedores que no sean confiables ni estén verificadas.
Aplica siempre el principio de privilegios mínimos y elige ejecutar contenedores no privilegiados.
Analiza las bibliotecas de código abierto en busca de vulnerabilidades para detectar servidores sin parches que aún puedan ser vulnerables a este CVE.