Abusing Roles/ClusterRoles in Kubernetes
Aquí puedes encontrar algunas configuraciones de Roles y ClusterRoles potencialmente peligrosas.
Recuerda que puedes obtener todos los recursos admitidos con kubectl api-resources
Escalada de Privilegios
Referido como el arte de obtener acceso a un principal diferente dentro del clúster con diferentes privilegios (dentro del clúster de Kubernetes o a nubes externas) de los que ya tienes, en Kubernetes básicamente existen 4 técnicas principales para escalar privilegios:
Ser capaz de suplantar a otros usuarios/grupos/SAs con mejores privilegios dentro del clúster de Kubernetes o a nubes externas
Ser capaz de crear/patch/ejecutar pods donde puedes encontrar o adjuntar SAs con mejores privilegios dentro del clúster de Kubernetes o a nubes externas
Ser capaz de leer secretos ya que los tokens de los SAs se almacenan como secretos
Ser capaz de escapar al nodo desde un contenedor, donde puedes robar todos los secretos de los contenedores en ejecución en el nodo, las credenciales del nodo y los permisos del nodo dentro de la nube en la que se está ejecutando (si los hay)
Una quinta técnica que merece mención es la capacidad de ejecutar port-forward en un pod, ya que podrías acceder a recursos interesantes dentro de ese pod.
Acceder a Cualquier Recurso o Verbo (Comodín)
El comodín (*) otorga permiso sobre cualquier recurso con cualquier verbo. Es utilizado por los administradores. Dentro de un ClusterRole esto significa que un atacante podría abusar de cualquier espacio de nombres en el clúster
Acceder a cualquier recurso con un verbo específico
En RBAC, ciertos permisos representan riesgos significativos:
create
: Concede la capacidad de crear cualquier recurso del clúster, lo que supone un riesgo de escalada de privilegios.list
: Permite listar todos los recursos, potencialmente filtrando datos sensibles.get
: Permite acceder a secretos de cuentas de servicio, representando una amenaza de seguridad.
Creación de Pod - Robo de Token
Un atacante con los permisos para crear un pod, podría adjuntar una Cuenta de Servicio privilegiada al pod y robar el token para hacerse pasar por la Cuenta de Servicio. Efectivamente escalando privilegios a la misma.
Ejemplo de un pod que robará el token de la cuenta de servicio bootstrap-signer
y lo enviará al atacante:
Creación y Escape de Pods
Lo siguiente indica todos los privilegios que un contenedor puede tener:
Acceso privilegiado (desactivando protecciones y estableciendo capacidades)
Desactivar los namespaces hostIPC y hostPid que pueden ayudar a escalar privilegios
Desactivar el namespace hostNetwork, dando acceso para robar privilegios de la nube de los nodos y un mejor acceso a las redes
Montar /hosts dentro del contenedor
Crear el pod con:
Una línea de este tweet y con algunas adiciones:
Ahora que puedes escapar al nodo, verifica las técnicas de post-explotación en:
Sigilo
Probablemente quieras ser más sigiloso, en las siguientes páginas puedes ver a qué podrías acceder si creas un pod solo habilitando algunos de los privilegios mencionados en la plantilla anterior:
Privilegiado + hostPID
Solo privilegiado
hostPath
hostPID
hostNetwork
hostIPC
Puedes encontrar ejemplos de cómo crear/abusar las configuraciones de pods privilegiados anteriores en https://github.com/BishopFox/badPods
Crear Pod - Mover a la nube
Si puedes crear un pod (y opcionalmente una cuenta de servicio), podrías ser capaz de obtener privilegios en el entorno de la nube al asignar roles de nube a un pod o una cuenta de servicio y luego acceder a ellos. Además, si puedes crear un pod con el espacio de nombres de red del host, puedes robar el rol IAM de la instancia del nodo.
Para más información, verifica:
Pod Escape PrivilegesCrear/Parchear Implementación, Conjuntos de demonios, Conjuntos con estado, Controladores de replicación, Conjuntos de réplicas, Trabajos y Trabajos cron
Es posible abusar de estos permisos para crear un nuevo pod y establecer privilegios como en el ejemplo anterior.
El siguiente yaml crea un conjunto de demonios y exfiltra el token de la SA dentro del pod:
Ejecución de Pods
pods/exec
es un recurso en Kubernetes utilizado para ejecutar comandos en una terminal dentro de un pod. Esto permite ejecutar comandos dentro de los contenedores o obtener una terminal interna.
Por lo tanto, es posible ingresar a un pod y robar el token del SA, o ingresar a un pod privilegiado, escapar al nodo, y robar todos los tokens de los pods en el nodo y (ab)usar el nodo:
port-forward
Esta permiso permite reenviar un puerto local a un puerto en el pod especificado. Esto está destinado a poder depurar aplicaciones que se ejecutan dentro de un pod fácilmente, pero un atacante podría abusar de ello para acceder a aplicaciones interesantes (como bases de datos) o vulnerables (¿páginas web?) dentro de un pod:
Escapar de /var/log/ Writable en Hosts
Como se indica en esta investigación, si puedes acceder o crear un pod con el directorio /var/log/
de los hosts montado en él, puedes escapar del contenedor.
Esto es básicamente porque cuando el Kube-API intenta obtener los logs de un contenedor (usando kubectl logs <pod>
), solicita el archivo 0.log
del pod utilizando el endpoint /logs/
del servicio Kubelet.
El servicio Kubelet expone el endpoint /logs/
que básicamente está exponiendo el sistema de archivos /var/log
del contenedor.
Por lo tanto, un atacante con acceso de escritura en la carpeta /var/log/ del contenedor podría abusar de este comportamiento de 2 maneras:
Modificando el archivo
0.log
de su contenedor (generalmente ubicado en/var/logs/pods/namespace_pod_uid/container/0.log
) para que sea un enlace simbólico que apunte a/etc/shadow
por ejemplo. Luego, podrás extraer el archivo shadow de los hosts haciendo:
Si el atacante controla algún principal con los permisos para leer
nodes/log
, simplemente puede crear un enlace simbólico en/host-mounted/var/log/sym
a/
y al acceder ahttps://<gateway>:10250/logs/sym/
listará el sistema de archivos raíz de los hosts (cambiando el enlace simbólico se puede acceder a archivos).
Se puede encontrar un laboratorio y un exploit automatizado en https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts
Saltando la protección de solo lectura
Si tienes la suerte suficiente y la capacidad altamente privilegiada CAP_SYS_ADMIN
está disponible, simplemente puedes remontar la carpeta como rw:
Saltándose la protección de solo lectura de hostPath
Según se indica en esta investigación es posible saltarse la protección:
Lo que se pretendía evitar escapes como los anteriores es, en lugar de usar un montaje hostPath, utilizar un PersistentVolume y un PersistentVolumeClaim para montar una carpeta de hosts en el contenedor con acceso de escritura:
Suplantación de cuentas privilegiadas
Con un privilegio de suplantación de usuario, un atacante podría suplantar una cuenta privilegiada.
Simplemente use el parámetro --as=<nombre de usuario>
en el comando kubectl
para suplantar a un usuario, o --as-group=<grupo>
para suplantar a un grupo:
O utiliza la API REST:
Listado de Secretos
La permisión para listar secretos podría permitir a un atacante leer realmente los secretos accediendo al punto final de la API REST:
Leyendo un secreto - forzando IDs de token
Mientras que un atacante en posesión de un token con permisos de lectura requiere el nombre exacto del secreto para usarlo, a diferencia del privilegio más amplio de listar secretos, aún existen vulnerabilidades. Las cuentas de servicio predeterminadas en el sistema pueden ser enumeradas, cada una asociada con un secreto. Estos secretos tienen una estructura de nombre: un prefijo estático seguido de un token alfanumérico aleatorio de cinco caracteres (excluyendo ciertos caracteres) según el código fuente.
El token se genera a partir de un conjunto limitado de 27 caracteres (bcdfghjklmnpqrstvwxz2456789
), en lugar del rango alfanumérico completo. Esta limitación reduce las posibles combinaciones totales a 14,348,907 (27^5). En consecuencia, un atacante podría ejecutar factiblemente un ataque de fuerza bruta para deducir el token en cuestión de horas, lo que potencialmente podría llevar a una escalada de privilegios al acceder a cuentas de servicio sensibles.
Solicitudes de Firma de Certificados
Si tienes los verbos create
en el recurso certificatesigningrequests
(o al menos en certificatesigningrequests/nodeClient
). Puedes crear un nuevo CeSR de un nuevo nodo.
Según la documentación es posible aprobar automáticamente estas solicitudes, por lo tanto, en ese caso no necesitas permisos adicionales. De lo contrario, necesitarías poder aprobar la solicitud, lo que implica actualizar en certificatesigningrequests/approval
y approve
en signers
con el nombre del recurso <signerNameDomain>/<signerNamePath>
o <signerNameDomain>/*
Un ejemplo de un rol con todos los permisos requeridos es:
Entonces, con la nueva CSR del nodo aprobada, puedes abusar de los permisos especiales de los nodos para robar secretos y escalar privilegios.
En este post y este otro la configuración de GKE K8s TLS Bootstrap está configurada con firma automática y se abusa para generar credenciales de un nuevo Nodo K8s y luego abusar de ellas para escalar privilegios al robar secretos. Si tienes los privilegios mencionados podrías hacer lo mismo. Ten en cuenta que el primer ejemplo evade el error que impide que un nuevo nodo acceda a secretos dentro de contenedores porque un nodo solo puede acceder a los secretos de los contenedores montados en él.
La forma de evadir esto es simplemente crear credenciales de nodo para el nombre del nodo donde está montado el contenedor con los secretos interesantes (pero solo verifica cómo hacerlo en el primer post):
Configmaps de aws-auth en AWS EKS
Los principios que pueden modificar configmaps
en el espacio de nombres kube-system en clústeres EKS (necesitan estar en AWS) pueden obtener privilegios de administrador de clúster sobrescribiendo el configmap aws-auth.
Los verbos necesarios son update
y patch
, o create
si el configmap no fue creado:
Puedes usar aws-auth
para persistencia dando acceso a usuarios de otras cuentas.
Sin embargo, aws --profile other_account eks update-kubeconfig --name <cluster-name>
no funciona desde una cuenta diferente. Pero en realidad aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing
funciona si colocas el ARN del clúster en lugar del nombre.
Para hacer que kubectl
funcione, asegúrate de configurar el kubeconfig de la víctima y en los argumentos de ejecución de aws agrega --profile other_account_role
para que kubectl use el perfil de la otra cuenta para obtener el token y contactar con AWS.
Escalando en GKE
Hay 2 formas de asignar permisos de K8s a los principales de GCP. En cualquier caso, el principal también necesita el permiso container.clusters.get
para poder recopilar credenciales para acceder al clúster, o necesitarás generar tu propio archivo de configuración de kubectl (sigue el siguiente enlace).
Al hablar con el punto final de la API de K8s, se enviará el token de autenticación de GCP. Luego, GCP, a través del punto final de la API de K8s, primero verificará si el principal (por correo electrónico) tiene algún acceso dentro del clúster, luego verificará si tiene algún acceso a través de GCP IAM. Si cualquiera de esos es verdadero, se le responderá. Si no, se dará un error sugiriendo dar permisos a través de GCP IAM.
Luego, el primer método es usando GCP IAM, los permisos de K8s tienen sus equivalentes permisos de GCP IAM, y si el principal los tiene, podrá usarlos.
GCP - Container PrivescEl segundo método es asignar permisos de K8s dentro del clúster identificando al usuario por su correo electrónico (se incluyen las cuentas de servicio de GCP).
Crear token de cuentas de servicio
Los principales que pueden crear solicitudes de token (serviceaccounts/token
) al hablar con el punto final de la API de K8s SAs (información de aquí).
ephemeralcontainers
Los principales que pueden actualizar
o parchear
pods/ephemeralcontainers
pueden obtener ejecución de código en otros pods, y potencialmente escapar a su nodo agregando un contenedor efímero con un securityContext privilegiado.
ValidatingWebhookConfigurations o MutatingWebhookConfigurations
Los principales con cualquiera de los verbos create
, update
o patch
sobre validatingwebhookconfigurations
o mutatingwebhookconfigurations
podrían ser capaces de crear uno de esos webhookconfigurations para poder escalar privilegios.
Para un ejemplo de mutatingwebhookconfigurations
revisa esta sección de esta publicación.
Escalar
Como se puede leer en la siguiente sección: Prevención de Escalada de Privilegios Incorporada, un principal no puede actualizar ni crear roles o clusterroles sin tener esos nuevos permisos. A menos que tenga el verbo escalate
sobre roles
o clusterroles
.
Entonces puede actualizar/crear nuevos roles, clusterroles con mejores permisos que los que tiene.
Proxy de nodos
Los principales con acceso al subrecurso nodes/proxy
pueden ejecutar código en pods a través de la API de Kubelet (según esto). Más información sobre la autenticación de Kubelet en esta página:
Tienes un ejemplo de cómo obtener RCE hablando autorizado a una API de Kubelet aquí.
Eliminar pods + nodos no programables
Los principales que pueden eliminar pods (verbo delete
sobre el recurso pods
), o expulsar pods (verbo create
sobre el recurso pods/eviction
), o cambiar el estado del pod (acceso a pods/status
) y pueden hacer que otros nodos no sean programables (acceso a nodes/status
) o eliminar nodos (verbo delete
sobre el recurso nodes
) y tienen control sobre un pod, podrían robar pods de otros nodos para que se ejecuten en el nodo comprometido y el atacante pueda robar los tokens de esos pods.
Estado de los servicios (CVE-2020-8554)
Los principios que pueden modificar services/status
pueden establecer el campo status.loadBalancer.ingress.ip
para explotar el CVE-2020-8554 sin corregir y lanzar ataques de MiTM contra el clúster. La mayoría de las mitigaciones para CVE-2020-8554 solo previenen servicios ExternalIP (según esto).
Estado de los Nodos y Pods
Los principios con permisos de update
o patch
sobre nodes/status
o pods/status
, podrían modificar etiquetas para afectar las restricciones de programación impuestas.
Prevención de Escalada de Privilegios Incorporada
Kubernetes tiene un mecanismo incorporado para prevenir la escalada de privilegios.
Este sistema asegura que los usuarios no pueden elevar sus privilegios modificando roles o vinculaciones de roles. La aplicación de esta regla ocurre a nivel de la API, proporcionando una protección incluso cuando el autorizador RBAC está inactivo.
La regla estipula que un usuario solo puede crear o actualizar un rol si posee todos los permisos que comprende el rol. Además, el alcance de los permisos existentes del usuario debe coincidir con el del rol que está intentando crear o modificar: ya sea a nivel de clúster para ClusterRoles o confinado al mismo espacio de nombres (o a nivel de clúster) para Roles.
Hay una excepción a la regla anterior. Si un principal tiene el verbo escalate
sobre roles
o clusterroles
puede aumentar los privilegios de roles y clusterroles incluso sin tener los permisos él mismo.
Obtener y Modificar RoleBindings/ClusterRoleBindings
Aparentemente esta técnica funcionaba antes, pero según mis pruebas ya no funciona por la misma razón explicada en la sección anterior. No puedes crear/modificar un rolebinding para darte a ti mismo o a un SA diferente algunos privilegios si no los tienes ya.
El privilegio de crear Rolebindings permite a un usuario vincular roles a una cuenta de servicio. Este privilegio puede llevar potencialmente a una escalada de privilegios porque permite al usuario vincular privilegios de administrador a una cuenta de servicio comprometida.
Otros Ataques
Aplicación de proxy sidecar
Por defecto no hay encriptación en la comunicación entre pods. Autenticación mutua, de dos vías, de pod a pod.
Crear una aplicación de proxy sidecar
Crea tu .yaml
Edita tu archivo .yaml y agrega las líneas descomentadas:
Ver los registros del proxy:
Más información en: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
Controlador de admisión malicioso
Un controlador de admisión intercepta las solicitudes al servidor de la API de Kubernetes antes de la persistencia del objeto, pero después de que la solicitud esté autenticada y autorizada.
Si un atacante logra de alguna manera inyectar un Controlador de Admisión de Mutación, podrá modificar solicitudes ya autenticadas. Teniendo potencialmente privilegios elevados y, más comúnmente, persistir en el clúster.
Ejemplo de https://blog.rewanthtammana.com/creating-malicious-admission-controllers:
Verifique el estado para ver si está listo:
![](https://cloud.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1628433436353%2FyHUvUWugR.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp&width=768&dpr=4&quality=100&sign=fe4bc7c0&sv=1)
Luego despliega un nuevo pod:
Cuando veas el error ErrImagePull
, verifica el nombre de la imagen con cualquiera de las consultas:
![](https://cloud.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1628433512073%2FleFXtgSzm.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp&width=768&dpr=4&quality=100&sign=45a94e54&sv=1)
Como puedes ver en la imagen anterior, intentamos ejecutar la imagen nginx
pero la imagen ejecutada finalmente es rewanthtammana/malicious-image
. ¿Qué acaba de suceder!!?
Aspectos técnicos
El fragmento anterior reemplaza la primera imagen del contenedor en cada pod con rewanthtammana/malicious-image
.
Bypass de OPA Gatekeeper
Kubernetes - OPA Gatekeeper bypassMejores Prácticas
Desactivar el Automontaje de Tokens de Cuenta de Servicio
Pods y Cuentas de Servicio: Por defecto, los pods montan un token de cuenta de servicio. Para mejorar la seguridad, Kubernetes permite desactivar esta función de automontaje.
Cómo Aplicar: Establecer
automountServiceAccountToken: false
en la configuración de cuentas de servicio o pods a partir de la versión 1.6 de Kubernetes.
Asignación de Usuario Restringida en RoleBindings/ClusterRoleBindings
Inclusión Selectiva: Asegurarse de que solo se incluyan los usuarios necesarios en RoleBindings o ClusterRoleBindings. Auditar regularmente y eliminar usuarios irrelevantes para mantener una seguridad estricta.
Roles Específicos del Espacio de Nombres sobre Roles en Todo el Cluster
Roles vs. ClusterRoles: Prefiera utilizar Roles y RoleBindings para permisos específicos del espacio de nombres en lugar de ClusterRoles y ClusterRoleBindings, que se aplican en todo el clúster. Este enfoque ofrece un control más preciso y limita el alcance de los permisos.
Utilizar herramientas automatizadas
Referencias
Last updated