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.

Secrets de Kubernetes y robo de tokens de cuenta de servicio

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.

Publicado el 7 min de lectura

TL;DR. El robo de credenciales en Kubernetes deja dos tipos de huellas. En el lado de los secrets: un list o watch sobre secrets sin namespace (todos los secrets del clúster, con su contenido), o una identidad que lee muchos secrets distintos en poco tiempo. En el lado de los tokens: una cuenta de servicio usada desde una IP pública o con kubectl/curl como user agent, una ráfaga de kubectl auth can-i, ráfagas de 403 y tokens nuevos emitidos con TokenRequest. Cada secret leído es una credencial que rotar, y en GKE las lecturas solo se registran si los logs de Data Access están activados.

Los secrets son la razón por la que la mayoría de los atacantes se molestan con un clúster: contraseñas de bases de datos, claves cloud, credenciales de registry, tokens de CI, claves de firma. ATT&CK lo clasifica como T1552.007, Container API, y la parte de tokens como T1528, Steal Application Access Token.

Cómo se filtran los secrets a través de la API

Las buenas prácticas de RBAC de Kubernetes subrayan algo que muchos equipos pasan por alto: list y watch sobre secrets revelan su contenido, igual que get. Un rol que «solo lista» secrets es un rol que los lee todos.

SolicitudRastro de auditoríaSignificado
kubectl get secrets -Alist sobre secrets, sin objectRef.namespaceTodos los secrets del clúster en una respuesta
kubectl get secrets -n shoplist sobre secrets, namespace shopTodos los secrets del namespace
kubectl get secret db-creds -o yamlget sobre secrets, con nombreUn secret
Crear un pod que monta un secretcreate sobre pods con un volumen secretLectura indirecta: quien puede crear pods puede leer los secrets que montan

La última fila importa: el permiso para crear workloads en un namespace concede implícitamente acceso a sus secrets y a sus tokens de cuentas de servicio. Esa lectura no aparece como un evento get secrets.

En los niveles por defecto de EKS y GKE, y en cualquier política sensata, los secrets se registran en Metadata: ves quién leyó qué secret, nunca el valor. Es suficiente para acotar la rotación.

La salvedad de GKE

En GKE, get y list van al log de auditoría de Data Access, que está desactivado por defecto (consulta la guía de exportación). Sin él, las lecturas de secrets no dejan ningún rastro. En AKS, la categoría más barata kube-audit-admin también descarta get y list.

Detecciones de secrets

El analizador de audit logs tiene dos reglas:

  • Secrets listados en todos los namespaces (alta): list o watch sobre secrets sin namespace, permitido, por una identidad que no es de sistema. Los controladores que vigilan legítimamente todos los secrets (por ejemplo, operadores de ingress o de certificados) deben añadirse a la lista de permitidos tras comprobarlo.
  • Ráfaga de lecturas de secrets (media): una identidad que lee 10 o más secrets distintos en 10 minutos. Contar nombres distintos evita marcar una aplicación que vuelve a leer su propio secret.

Los kubelets (system:node:*) leen todo el día los secrets de los pods programados en su nodo; es normal y está excluido.

Cómo se roban los tokens de cuentas de servicio

Los pods reciben un token de su cuenta de servicio, montado por defecto en /var/run/secrets/kubernetes.io/serviceaccount/token. Desde Kubernetes 1.22 son tokens de corta duración, rotados automáticamente y obtenidos a través de la API TokenRequest; desde la 1.24, los tokens de larga duración guardados en Secrets ya no se crean automáticamente, según la documentación de cuentas de servicio. Los Secrets de tokens heredados, creados a mano o antes de una actualización, siguen presentes en muchos clústeres.

Vías de robo típicas:

  • leer el token montado tras explotar una aplicación (RCE, SSRF, path traversal);
  • kubectl exec … cat /var/run/secrets/kubernetes.io/serviceaccount/token;
  • leer un Secret de token heredado, un kubeconfig guardado en un Secret o una variable de CI;
  • un dashboard o herramienta expuestos que corren con una cuenta de servicio con demasiados privilegios;
  • emitir un token nuevo con kubectl create token (TokenRequest) cuando RBAC permite create sobre serviceaccounts/token.

Cómo se ve un token reutilizado

Un token usado por su workload sigue un patrón estable: IPs de pods, el user agent propio de la aplicación y las mismas pocas llamadas a la API. Un token reutilizado rompe ese patrón:

SeñalRegla del analizadorSeveridad
Solicitud de una cuenta de servicio desde una IP pública (Internet)Token de cuenta de servicio usado desde una IP públicaAlta
Cuenta de servicio con user agent kubectl/, curl/, python-requests/, Go-http-client/…Token de cuenta de servicio usado con kubectl / curlMedia
5 o más selfsubjectaccessreviews / selfsubjectrulesreviews en 5 minutosEnumeración de permisos (kubectl auth can-i)Media
10 o más respuestas 403 en 10 minutosRáfaga de solicitudes denegadasMedia
User agent de kube-hunter, peirates, kubeletctl, kubiscan…User agent de una herramienta de ataque para KubernetesAlta
create sobre serviceaccounts/tokenToken de cuenta de servicio generadoMedia

kubectl auth can-i --list produce una SelfSubjectRulesReview; kubectl auth can-i create pods, una SelfSubjectAccessReview. Los workloads rara vez llaman a ninguna de las dos, así que una ráfaga desde una cuenta de servicio es alguien descubriendo qué puede hacer con su token robado (ATT&CK T1613).

Salvedades que conviene tener presentes:

  • El user agent lo controla el cliente. Su ausencia no prueba nada; su presencia sigue siendo una buena pista.
  • La IP de origen se toma de la última entrada de sourceIPs. En clústeres detrás de un proxy o con endpoint privado, puede que nunca aparezca una dirección «pública».
  • Algunos operadores escritos en Go usan un agente genérico Go-http-client. Compruébalo antes de escalar.

Seguir un token

Las versiones recientes de Kubernetes añaden un identificador de credencial (el JTI del token) en user.extra para los tokens de cuentas de servicio. Cuando está presente, permite distinguir dos tokens de la misma cuenta de servicio: el que usa el pod y el que el atacante copió o emitió. Pivota sobre él igual que sobre una IP.

En una TokenRequest, el cuerpo de la solicitud (registrado en nivel Request en EKS y en la política recomendada) muestra expirationSeconds y las audiencias. Un token pedido para un año (31536000) por un cliente interactivo es un paso de persistencia, no una renovación de un workload. El API server puede limitar la vida de los tokens con --service-account-max-token-expiration.

Alcance y remediación

  1. Lista cada secret leído por las identidades comprometidas, incluidos los de las respuestas de list globales: ante un list de todo el clúster, asume que todos los secrets quedaron expuestos.
  2. Rótalos en origen: la contraseña de la base de datos, la clave de acceso cloud, la credencial del registry, no solo el objeto Secret de Kubernetes.
  3. Invalida los tokens. Los tokens ligados mueren con el objeto al que están ligados; los emitidos con TokenRequest siguen siendo válidos hasta que caducan salvo que borres la cuenta de servicio. Borrar y volver a crear la cuenta de servicio, y reiniciar después sus workloads, es la salida fiable. Borra los Secrets de tokens heredados.
  4. Encuentra el punto de entrada: el pod que filtró el token, el dashboard, el job de CI.
  5. Corta el camino: automountServiceAccountToken: false donde no se necesite la API, roles de mínimo privilegio sin list sobre secrets, y nada de create sobre serviceaccounts/token fuera de los controladores.

Revisa también el lado cloud: una clave cloud robada de un Secret se usa contra la API del proveedor, no contra Kubernetes. Los sitios hermanos AWS Forensics, GCP Forensics y Azure Forensics cubren esos logs.

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.
Encuentra escaladas de privilegios RBAC de Kubernetes en los audit logs: bindings a cluster-admin, verbos escalate, bind e impersonate, acceso anónimo.

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.