¿Necesita Cloud Computing? Empiece ahora

Imposible de contener: detección de una vulnerabilidad de inyección de comandos en Kubernetes

Tomer Peled

escrito por

Tomer Peled

September 13, 2023

Tomer Peled

escrito por

Tomer Peled

Tomer Peled es investigador de seguridad en Akamai. En su trabajo diario, lleva a cabo investigaciones que incluyen desde las vulnerabilidades hasta los aspectos internos del sistema operativo. En su tiempo libre, le gusta cocinar, practicar krav magá y jugar en su PC.

Es importante que los administradores apliquen el parche más reciente a sus clústeres de Kubernetes para evitar ataques que aprovechen estas vulnerabilidades.

Comentario editorial y adicional de Tricia Howard

Resumen ejecutivo

  • Tomer Peled, investigador de seguridad de Akamai, ha detectado recientemente una vulnerabilidad de gravedad alta en Kubernetes a la que se le ha asignado el código CVE-2023-3676 y una puntuación de CVSS de 8,8.

  • Este descubrimiento permitió identificar dos vulnerabilidades más, ya que comparten la misma causa raíz: llamada de funciones inseguras y falta de saneamiento en los datos introducidos por el usuario.

  • La vulnerabilidad permite la ejecución remota de código con privilegios del SISTEMA en todos los terminales de Windows de un clúster de Kubernetes. Para perpetrar un ataque aprovechando esta vulnerabilidad, el atacante debe aplicar un archivo YAML malicioso en el clúster.

  • Esta vulnerabilidad se puede aprovechar en las instalaciones predeterminadas de Kubernetes y se ha probado tanto en implementaciones locales como en Azure Kubernetes Service.

  • Ofrecemos una prueba de concepto de un archivo YAML, así como una regla OPA para bloquear esta vulnerabilidad.

Introducción

YAML (siglas de YAML Ai't Markup Language) es un lenguaje de serialización de datos similar a JSON que se utiliza principalmente en archivos de configuración. Por ello, desempeña un papel fundamental en Kubernetes, el nuevo y extendido sistema de orquestación de contenedores que ayuda a las organizaciones a automatizar la implementación, el escalado y la gestión de aplicaciones contenedorizadas. El marco de Kubernetes utiliza archivos YAML prácticamente para todo, desde la configuración de la interfaz de red de contenedores hasta la gestión de módulos e incluso la gestión de secretos.

Los archivos YAML de Kubernetes han sido objeto de investigación en los últimos años. Teniendo en cuenta que Kubernetes se basa en YAML para la configuración de clústeres, este tema de investigación resulta especialmente interesante.

¿Cómo se han aprovechado las vulnerabilidades de YAML y Kubernetes en el pasado?

En 2022, se detectó la vulnerabilidad CVE-2022-1471 dentro del constructor de SnakeYAML, un famoso analizador de archivos YAML. La vulnerabilidad permitía la creación de objetos no seguros, lo que podría dar lugar a la ejecución de código en aplicaciones vulnerables que lo utilizan. Otro ejemplo que muestra el posible impacto de los archivos YAML se puede ver en este aviso de CVE acerca de la vulnerabilidad CVE-2021-25749 elaborado por el equipo de seguridad de Kubernetes. Esta vulnerabilidad permite a los atacantes omitir la verificación de quién puede acceder a la raíz escribiendo incorrectamente su nombre en el archivo YAML.

Como parte de nuestra investigación sobre Kubernetes, detectamos las vulnerabilidades CVE-2017-1002101 y CVE-2021-25741. Estas vulnerabilidades pusieron de manifiesto cómo los atacantes pueden utilizar condiciones de carrera y enlaces simbólicos junto con la subpropiedad subPath en un archivo YAML para obtener acceso a datos con privilegios fuera del contenedor. 

Estas vulnerabilidades anteriores nos inspiraron a seguir la dirección del procesamiento de rutas en la base de código de Kubernetes, lo que finalmente llevó a descubrir la vulnerabilidad de la que estamos hablando hoy.

En esta entrada del blog, mostraremos cómo un atacante con privilegios de "aplicación" (los privilegios necesarios para interactuar con la API de Kubernetes) puede inyectar código que se ejecutará en equipos Windows remotos con privilegios del SISTEMA.

Detalles de la vulnerabilidad

Cuando se crea un módulo, el usuario tiene la opción de crear un directorio compartido entre el módulo y el host. Esta función (denominada volumes) es útil, por ejemplo, al servir sitios web a través de un contenedor en un módulo. Es posible que queramos compartir los archivos del sitio desde un directorio compartido con el host; de esta forma, podríamos cambiar el diseño del sitio como quisiéramos y no necesitaríamos volver a compilar una imagen que contenga el sitio cada vez.

Para activar los volúmenes, hay que incluir el parámetro volume en el archivo YAML del módulo. Las ubicaciones donde montar el volumen se enumeran en mountPath (la ubicación en el contenedor) y hostPath (la ubicación en el host).

Para nosotros, lo más importante es que podemos montar nuestro directorio o archivo compartido en una ubicación seleccionada utilizando la subpropiedad subPath. Todas las propiedades relevantes para los volúmenes se pueden ver en la Figura 1.

Todas las propiedades relevantes para los volúmenes se pueden ver en la Figura 1. Fig. 1: Configuración de volúmenes de YAML

El análisis de nuestro archivo YAML lo realiza kubelet: un servicio central de Kubernetes que se encarga de ejecutar las aplicaciones contenedorizadas en un nodo. Como parte del parche para CVE-2021-25741, kubelet valida todos los parámetros del archivo YAML y también garantiza que no se creen enlaces simbólicos como resultado del uso del parámetro subPath; para ello, realiza una llamada a la función interna "isLinkPath". La función se muestra en la Figura 2.

 

Función subPath Fig. 2: Función subPath para comprobar las rutas de enlace simbólico

La función toma como parámetro la subruta proporcionada por el usuario en el archivo YAML. A continuación, utiliza esta ruta para crear un comando de PowerShell para determinar el tipo de ruta (es decir, si es un enlace simbólico o no). El comando de PowerShell con formato se invoca inmediatamente mediante la llamada de la función "exec.Command".

La presencia de "exec.Command" junto con la falta de saneamiento en los datos introducidos por el usuario abre las puertas para perpetrar un ataque de inyección de comandos.

PowerShell permite a los usuarios evaluar los valores dentro de las cadenas antes de utilizarlas. Esto se puede hacer añadiendo $(<expresión_para_evaluar>) a la cadena. La Figura 3 muestra un ejemplo.

  PS> echo “the value of 1+1 is $(1+1)

  Output:
  the value of 1+1 is 2

Fig. 3: Ejemplo de evaluación de expresiones de PowerShell dentro de cadenas

Este ejemplo es muy sencillo, pero se puede insertar cualquier comando de PowerShell entre paréntesis para evaluarlo como, por ejemplo, $(Start-Process cmd), $(Invoke-Expression exp) y otros elementos de PowerShell.

Un atacante puede hacer un uso indebido de la evaluación de subruta para acceder al código vulnerable y ejecutar cualquier comando que desee con privilegios del SISTEMA (el propio contexto de kubelet) desde nodos remotospara así hacerse con el control de todos los nodos de Windows del clúster. La Figura 4 muestra un valor de subPath malicioso.

 Archivo YAML Fig. 4: Archivo YAML con inyección de comandos en el parámetro subPath

Prueba de concepto de demostración de CVE-2023-3676

La prueba de concepto es simplemente un archivo YAML que contiene la evaluación del comando de PowerShell. Encontrará este archivo, así como un vídeo que muestra el inicio del terminal, en nuestro repositorio de GitHub.

Esta CVE ayudó a detectar y corregir otras vulnerabilidades de inyección de comandos. Se les asignaron colectivamente los códigos CVE-2023-3955 y CVE-2023-3893.

Análisis de parches

El equipo de Kubernetes decidió aplicar parches a esta clase de vulnerabilidades transfiriendo los parámetros desde variables de entorno en lugar de hacerlo desde los datos introducidos por el usuario (Figura 5). Al transferir los valores de esta manera, los parámetros se tratan como cadenas; por lo tanto, PowerShell no los evaluará como expresiones.

Función patch Fig. 5: Función con parche aplicado para CVE-2023-3676

¿Soy vulnerable?

Como hemos mencionado anteriormente, todas las versiones de Kubernetes anteriores a la 1.28 son vulnerables a esta CVE. Existen varios métodos para determinar si uno de los nodos del clúster es un nodo de Windows. Un método consiste en ejecutar el comando de la Figura 6.

kubectl get nodes -o wide --show-labels | grep “os=windows”


Resultados:

akswin000000                        Ready    agent   4d17h   v1.26.6   agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows…


akswin000001                        Ready    agent   4d17h   v1.26.6   agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows…

Fig. 6: Comando kubectl para determinar si uno de los nodos del clúster es un nodo de Windows

Mitigación

La aplicación de parches es la forma más fiable de protegerse de esta vulnerabilidad. Si no fuera posible aplicar parches, hemos descrito varias alternativas para protegerse contra esta vulnerabilidad; elija la que mejor se adapte a su entorno.

Soluciones anteriores

En el caso de la vulnerabilidad CVE-2023-3676, los administradores de Kubernetes pueden deshabilitar el uso de Volume.Subpath. Esto garantizará que el clúster esté a salvo de esta vulnerabilidad, pero deshabilitará un mecanismo que a veces es importante para los clústeres en producción.

OPA

Open Policy Agent (OPA) es un agente de código abierto que permite a los usuarios recibir datos sobre el tráfico que entra y sale de los nodos y tomar medidas basadas en políticas sobre los datos recibidos. OPA utiliza Rego como lenguaje para su motor; con él, los administradores pueden crear reglas para bloquear la implementación de determinados archivos YAML. La Figura 7 muestra una regla que impide la creación de módulos con una subruta maliciosa.

  package kubernetes.admission

  deny[msg] {                                                                 
    input.request.kind.kind == "Pod"
    path := input.request.object.spec.containers.volumeMounts.subPath                 
    not startswith(path, "$(")                                     
    msg := sprintf("malicious path: %v was found", [path])     
}

Fig. 7: Regla para impedir la creación de módulos con una subruta maliciosa

RBAC

El control de acceso basado en funciones (RBAC) es un método que segmenta las operaciones de usuario según el usuario en cuestión. Por ejemplo, los usuarios solo podrán crear módulos en su propio espacio de nombres o solo podrán ver la información de los espacios de nombres para los que tienen permiso. Esto puede ayudar a limitar el número de usuarios que pueden realizar acciones en un clúster y ayuda a centrar la atención en aquellos que sí tienen los privilegios pertinentes para su uso.

Conclusión

La vulnerabilidad CVE-2023-3676 requiere pocos privilegios y, por lo tanto, ofrece una oportunidad fácil de aprovechar para los atacantes: solo tienen que acceder a un nodo y aplicar privilegios. Como hemos comentado en esta entrada del blog, si el atacante consigue aprovechar con éxito esta vulnerabilidad, podrá ejecutar código de forma remota en cualquier nodo de Windows del equipo con privilegios del SISTEMA.

Esta vulnerabilidad es muy fácil de aprovechar y tiene un impacto considerable, así que es frecuente ver este tipo de ataque (y otros similares) en organizaciones. De hecho, la única barrera de esta vulnerabilidad es su alcance, ya que se limita a los nodos de Windows, cuyo uso no está muy extendido.

Es importante que los administradores apliquen el parche más reciente a sus clústeres de Kubernetes para evitar ataques que aprovechen estas vulnerabilidades. Si no es posible aplicar los parches de inmediato, le recomendamos que utilice uno de los métodos descritos anteriormente para protegerse de esta vulnerabilidad.

Queremos agradecer al equipo de Kubernetes por su rápida respuesta y su comunicación.

Tiempo de divulgación

  • 13/07/2023: Vulnerabilidad revelada al equipo de Kubernetes.

  • 19/07/2023: CVE asignadas por el equipo de Kubernetes

  • 23/08/2023: Publicación por parte de Kubernetes de las correcciones para las CVE 

  • 13/09/2023: Publicación de la entrada del blog



Tomer Peled

escrito por

Tomer Peled

September 13, 2023

Tomer Peled

escrito por

Tomer Peled

Tomer Peled es investigador de seguridad en Akamai. En su trabajo diario, lleva a cabo investigaciones que incluyen desde las vulnerabilidades hasta los aspectos internos del sistema operativo. En su tiempo libre, le gusta cocinar, practicar krav magá y jugar en su PC.