Skip to content

Esta herramienta no está afiliada a The Linux Foundation, la Cloud Native Computing Foundation (CNCF) ni el proyecto Kubernetes, ni está respaldada ni patrocinada por ellos. Kubernetes y K8s son marcas registradas de The Linux Foundation. EKS, GKE, AKS y otros nombres son marcas comerciales de sus respectivos propietarios.

Escalada de privilegios RBAC en Kubernetes: cómo detectarla

Encuentra escaladas de privilegios RBAC de Kubernetes en los audit logs: bindings a cluster-admin, verbos escalate, bind e impersonate, acceso anónimo.

Publicado el 6 min de lectura

TL;DR. En el audit log, una escalada RBAC es una escritura: un create, update o patch sobre clusterrolebindings, rolebindings, clusterroles o roles. Las peligrosas enlazan cluster-admin, conceden los verbos escalate, bind o impersonate o comodines *, o nombran a system:anonymous / system:unauthenticated. Necesitas los cuerpos de las solicitudes (nivel Request) para ver el roleRef y los subjects. Mira también el campo impersonatedUser y recuerda que el IAM cloud puede dar acceso al clúster sin ningún objeto RBAC de Kubernetes.

Un binding nuevo a cluster-admin es la señal más fiable de una intrusión seria en Kubernetes: así es como un atacante convierte un token prestado en una identidad permanente. ATT&CK lo recoge como T1098.006, Additional Container Cluster Roles.

RBAC en una tabla

El RBAC tiene cuatro tipos de objetos:

ObjetoÁmbitoConcede
RoleNamespaceReglas (verbos sobre recursos) dentro de un namespace
ClusterRoleClústerReglas sobre recursos de clúster, o reutilizables entre namespaces
RoleBindingNamespaceUn Role o ClusterRole a sujetos, dentro de un namespace
ClusterRoleBindingClústerUn ClusterRole a sujetos, en todas partes

El roleRef del binding nombra el rol; subjects lista usuarios, grupos o cuentas de servicio. Ambos van en el cuerpo de la solicitud, así que una política que registra las escrituras RBAC en Metadata te dice «se creó un ClusterRoleBinding llamado node-health-admin» y nada sobre lo que concede.

Los verbos de prevención de escalada

Kubernetes bloquea la escalada ingenua: la documentación de RBAC explica que solo puedes crear o modificar un rol con permisos que ya tienes, y solo enlazar un rol cuyos permisos ya tienes. Tres verbos levantan esos controles:

  • escalate sobre roles o clusterroles: escribir un rol con más permisos de los que tienes.
  • bind sobre roles o clusterroles: enlazar un rol que no tienes, incluido cluster-admin.
  • impersonate sobre usuarios, grupos o cuentas de servicio: actuar como otro.

Las buenas prácticas de RBAC incluyen los tres entre los riesgos de escalada de privilegios, junto con los comodines *, que además cubren cualquier tipo de recurso que se añada en el futuro. Un rol que concede cualquiera de ellos a una persona o workload es un camino hacia cluster-admin.

Detecciones

El analizador de audit logs revisa las escrituras RBAC con estas reglas:

ReglaSeveridadLógica
Binding a cluster-admin creadoCrítica(Cluster)RoleBinding con roleRef.name: cluster-admin
Acceso concedido a usuarios anónimos / no autenticadosCríticaBinding con sujeto system:anonymous o system:unauthenticated
El rol otorga escalate / bind / impersonate o comodinesAlta(Cluster)Role escrito con esos verbos o con verbos/recursos *
Solicitud realizada suplantando otra identidadMediaimpersonatedUser presente
Solicitud anónima permitidaAltasystem:anonymous permitido más allá de los endpoints de salud, versión y descubrimiento OIDC
Role binding a nivel de clúster creadoBajaCualquier ClusterRoleBinding escrito por una identidad que no es de sistema

La regla de severidad baja existe por el hueco de registro mencionado antes: cuando falta el cuerpo, un ClusterRoleBinding nuevo sigue mereciendo un vistazo, y la anotación authorization.k8s.io/reason de las solicitudes posteriores lo nombrará cuando se use.

Leer un binding malicioso

Un ejemplo ficticio, registrado en nivel RequestResponse:

{
  "verb": "create",
  "user": { "username": "system:serviceaccount:kubernetes-dashboard:kubernetes-dashboard" },
  "sourceIPs": ["203.0.113.45"],
  "userAgent": "kubectl/v1.30.2 (linux/amd64) kubernetes/3968350",
  "objectRef": { "resource": "clusterrolebindings", "name": "node-health-admin",
                 "apiGroup": "rbac.authorization.k8s.io" },
  "requestObject": {
    "kind": "ClusterRoleBinding",
    "metadata": { "name": "node-health-admin" },
    "roleRef": { "apiGroup": "rbac.authorization.k8s.io", "kind": "ClusterRole", "name": "cluster-admin" },
    "subjects": [ { "kind": "ServiceAccount", "name": "node-health", "namespace": "kube-system" } ]
  },
  "responseStatus": { "code": 201 }
}

Destacan tres cosas: una cuenta de servicio creando objetos RBAC, desde una dirección de Internet, con kubectl; un nombre elegido para parecer un componente del sistema; y una cuenta de servicio nueva en kube-system como sujeto. El siguiente paso del atacante suele ser una TokenRequest para esa cuenta de servicio, que le da una credencial independiente de la que robó al principio. El recorrido ficticio sigue exactamente esta secuencia.

Impersonation

Quien tenga el permiso impersonate puede enviar las cabeceras Impersonate-User, Impersonate-Group (y relacionadas); la solicitud se autoriza entonces como la identidad suplantada. El evento de auditoría conserva ambas: user es quien llamó de verdad e impersonatedUser quien dijo ser. Informa siempre de las dos y revisa quién tiene impersonate: en la mayoría de los clústeres esa lista debería ser muy corta.

kubectl --as=<user> y --as-group usan estas cabeceras; algunos proxies de acceso y dashboards también, por eso el analizador marca la impersonation con severidad media y deja el juicio en tus manos.

Acceso anónimo

Salvo que se desactive, las solicitudes sin credenciales se autentican como system:anonymous en el grupo system:unauthenticated, como describe la documentación de autenticación. Los endpoints de salud y descubrimiento suelen estar abiertos. Un binding que conceda algo más a estos sujetos significa que cualquiera que pueda alcanzar el API server tiene esos derechos. Consulta la entrada del glosario system:anonymous para ver los ajustes que lo controlan.

Vías de escalada sin escritura RBAC

No toda escalada aparece como un binding:

  • IAM cloud. En EKS, las access entries y el ConfigMap aws-auth asocian principales de IAM a identidades de Kubernetes; asociar una política de acceso de administrador a una access entry ocurre en la API de AWS (CloudTrail), no en el audit log de Kubernetes. GKE concede acceso al clúster mediante roles de IAM de Google Cloud, y AKS mediante asignaciones de roles de Azure RBAC cuando está activado Azure RBAC para Kubernetes. Revisa estos cambios en los logs del plano de control cloud.
  • Agregación de ClusterRoles. Un ClusterRole con etiquetas que coinciden con una aggregationRule ve sus reglas fusionadas en el rol agregado. Añadir un rol así amplía en silencio todos los bindings del rol agregado.
  • Creación de workloads. Quien puede crear pods en un namespace puede montar cualquier cuenta de servicio de ese namespace y actuar como ella. Consulta secrets y robo de tokens.
  • Certificados. El permiso para aprobar CertificateSigningRequests permite emitir certificados de cliente para identidades arbitrarias.
  • Webhooks de admisión. Controlar la configuración de los webhooks permite ver o reescribir objetos al crearse.

Consultas de búsqueda

Líneas JSON en bruto, bindings a cluster-admin:

jq -c 'select((.objectRef.resource == "clusterrolebindings" or .objectRef.resource == "rolebindings")
              and (.verb == "create" or .verb == "update" or .verb == "patch")
              and .requestObject.roleRef.name == "cluster-admin")
       | {t: .requestReceivedTimestamp, user: .user.username, ip: .sourceIPs,
          name: .objectRef.name, subjects: .requestObject.subjects}' audit.log

EKS, CloudWatch Logs Insights, todas las escrituras RBAC:

fields @timestamp, user.username, verb, objectRef.resource, objectRef.name
| filter @logStream like "kube-apiserver-audit"
| filter objectRef.apiGroup = "rbac.authorization.k8s.io"
| filter verb in ["create", "update", "patch", "delete"]
| sort @timestamp desc

Remediación

  1. Guarda los objetos implicados (kubectl get clusterrolebinding <name> -o yaml) como evidencia y luego bórralos.
  2. Borra y vuelve a crear cualquier cuenta de servicio que recibiera cluster-admin, para que los tokens emitidos para ella dejen de funcionar.
  3. Revisa todos los bindings a cluster-admin y a roles que pueden escribir RBAC, leer secrets o hacer exec en pods.
  4. Quita escalate, bind, impersonate y los comodines de los roles que no los necesiten estrictamente.
  5. Desactiva la autenticación anónima o limítala a los endpoints de salud.

Artículos relacionados

Artículos relacionados

Detecta criptominería en clústeres de Kubernetes con los audit logs: imágenes y argumentos de mineros, registries inusuales, persistencia con CronJob.
Detecta la preparación de un escape de contenedor en los audit logs de Kubernetes: pods privilegiados, hostPID, hostPath de / y DaemonSets en kube-system.
Detecta robo de secrets y tokens de cuentas de servicio de Kubernetes en los audit logs: list globales, ráfagas, TokenRequest, uso desde IP pública, can-i.

Esta herramienta no está afiliada a The Linux Foundation, la Cloud Native Computing Foundation (CNCF) ni el proyecto Kubernetes, ni está respaldada ni patrocinada por ellos. Kubernetes y K8s son marcas registradas de The Linux Foundation. EKS, GKE, AKS y otros nombres son marcas comerciales de sus respectivos propietarios.