AWS - EKS Post Exploitation

Aprende a hackear AWS de cero a héroe con htARTE (Experto en Equipos Rojos de AWS de HackTricks)!

Otras formas de apoyar a HackTricks:

EKS

Para más información consulta

pageAWS - EKS Enum

Enumerar el clúster desde la Consola de AWS

Si tienes el permiso eks:AccessKubernetesApi puedes ver objetos de Kubernetes a través de la consola de AWS EKS (Aprende más).

Conectar al Clúster de Kubernetes de AWS

  • Forma sencilla:

# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
  • No es tan fácil:

Si puedes obtener un token con aws eks get-token --name <cluster_name> pero no tienes permisos para obtener información del clúster (describeCluster), podrías preparar tu propio ~/.kube/config. Sin embargo, teniendo el token, aún necesitas la URL de conexión al endpoint (si lograste obtener un token JWT desde un pod, lee aquí) y el nombre del clúster.

En mi caso, no encontré la información en los registros de CloudWatch, pero la encontré en el userData de LaunchTemplates y también en userData de las máquinas EC2. Puedes ver esta información en userData fácilmente, por ejemplo en el siguiente ejemplo (el nombre del clúster era cluster-name):

API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com

/etc/eks/bootstrap.sh cluster-name --kubelet-extra-args '--node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=cluster-name,alpha.eksctl.io/nodegroup-name=prd-ondemand-us-west-2b,role=worker,eks.amazonaws.com/nodegroup-image=ami-002539dd2c532d0a5,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=prd-ondemand-us-west-2b,type=ondemand,eks.amazonaws.com/sourceLaunchTemplateId=lt-0f0f0ba62bef782e5 --max-pods=58' --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL --dns-cluster-ip $K8S_CLUSTER_DNS_IP --use-max-pods false
configuración de kube

```yaml describe-cache-parametersapiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1USXlPREUyTWpjek1Wb1hEVE15TVRJeU5URTJNamN6TVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDlXCk9OS0ZqeXZoRUxDZGhMNnFwWkMwa1d0UURSRVF1UzVpRDcwK2pjbjFKWXZ4a3FsV1ZpbmtwOUt5N2x2ME5mUW8KYkNqREFLQWZmMEtlNlFUWVVvOC9jQXJ4K0RzWVlKV3dzcEZGbWlsY1lFWFZHMG5RV1VoMVQ3VWhOanc0MllMRQpkcVpzTGg4OTlzTXRLT1JtVE5sN1V6a05pTlUzSytueTZSRysvVzZmbFNYYnRiT2kwcXJSeFVpcDhMdWl4WGRVCnk4QTg3VjRjbllsMXo2MUt3NllIV3hhSm11eWI5enRtbCtBRHQ5RVhOUXhDMExrdWcxSDBqdTl1MDlkU09YYlkKMHJxY2lINjYvSTh0MjlPZ3JwNkY0dit5eUNJUjZFQURRaktHTFVEWUlVSkZ4WXA0Y1pGcVA1aVJteGJ5Nkh3UwpDSE52TWNJZFZRRUNQMlg5R2c4Q0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQVXFsekhWZmlDd0xqalhPRmJJUUc3L0VxZ1hNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBS1o4c0l4aXpsemx0aXRPcGcySgpYV0VUSThoeWxYNWx6cW1mV0dpZkdFVVduUDU3UEVtWW55eWJHbnZ5RlVDbnczTldMRTNrbEVMQVE4d0tLSG8rCnBZdXAzQlNYamdiWFovdWVJc2RhWlNucmVqNU1USlJ3SVFod250ZUtpU0J4MWFRVU01ZGdZc2c4SlpJY3I2WC8KRG5POGlHOGxmMXVxend1dUdHSHM2R1lNR0Mvd1V0czVvcm1GS291SmtSUWhBZElMVkNuaStYNCtmcHUzT21UNwprS3VmR0tyRVlKT09VL1c2YTB3OTRycU9iSS9Mem1GSWxJQnVNcXZWVDBwOGtlcTc1eklpdGNzaUJmYVVidng3Ci9sMGhvS1RqM0IrOGlwbktIWW4wNGZ1R2F2YVJRbEhWcldDVlZ4c3ZyYWpxOUdJNWJUUlJ6TnpTbzFlcTVZNisKRzVBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== server: https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-west-2.eks.amazonaws.com name: arn:aws:eks:us-east-1::cluster/ contexts: - context: cluster: arn:aws:eks:us-east-1::cluster/ user: arn:aws:eks:us-east-1::cluster/ name: arn:aws:eks:us-east-1::cluster/ current-context: arn:aws:eks:us-east-1::cluster/ kind: Config preferences: {} users: - name: arn:aws:eks:us-east-1::cluster/ user: exec: apiVersion: client.authentication.k8s.io/v1beta1 args: - --region - us-west-2 - --profile - - eks - get-token - --cluster-name - command: aws env: null interactiveMode: IfAvailable provideClusterInfo: false ```

De AWS a Kubernetes

El creador del cluster EKS SIEMPRE podrá acceder al cluster de Kubernetes como parte del grupo system:masters (admin de k8s). En el momento de escribir esto, no hay una forma directa de encontrar quién creó el cluster (puedes verificar en CloudTrail). Y no hay forma de eliminar ese privilegio.

La forma de otorgar acceso sobre K8s a más usuarios o roles de AWS IAM es utilizando el configmap aws-auth.

Por lo tanto, cualquier persona con acceso de escritura sobre el configmap aws-auth podrá comprometer todo el cluster.

Para obtener más información sobre cómo otorgar privilegios adicionales a roles y usuarios de IAM en la misma cuenta o en cuentas diferentes y cómo abusar de esto, visita esta página.

Consulta también este increíble post para aprender cómo funciona la autenticación IAM -> Kubernetes.

De Kubernetes a AWS

Es posible permitir una autenticación OpenID para la cuenta de servicio de Kubernetes para permitirles asumir roles en AWS. Aprende cómo funciona esto en esta página.

Obtener el Endpoint del Servidor Api desde un Token JWT

https://<cluster-id>.<two-random-chars><number>.<region>.eks.amazonaws.com

No encontré ninguna documentación que explique los criterios para los 'dos caracteres' y el 'número'. Pero al hacer algunas pruebas por mi cuenta, veo que se repiten estos:

  • gr7

  • yl4

De todos modos, al ser solo 3 caracteres, podemos probar a fuerza bruta. Utiliza el siguiente script para generar la lista

from itertools import product
from string import ascii_lowercase

letter_combinations = product('abcdefghijklmnopqrstuvwxyz', repeat = 2)
number_combinations = product('0123456789', repeat = 1)

result = [
f'{''.join(comb[0])}{comb[1][0]}'
for comb in product(letter_combinations, number_combinations)
]

with open('out.txt', 'w') as f:
f.write('\n'.join(result))

Entonces con wfuzz

wfuzz -Z -z file,out.txt --hw 0 https://<cluster-id>.FUZZ.<region>.eks.amazonaws.com

Recuerda reemplazar y <región>.

Saltar CloudTrail

Si un atacante obtiene credenciales de un AWS con permisos sobre un EKS. Si el atacante configura su propio kubeconfig (sin llamar a update-kubeconfig) como se explicó anteriormente, el get-token no genera registros en CloudTrail porque no interactúa con la API de AWS (solo crea el token localmente).

Entonces, cuando el atacante habla con el clúster EKS, cloudtrail no registrará nada relacionado con el usuario que fue robado y accedió a él.

Ten en cuenta que el clúster EKS podría tener habilitados registros que registrarán este acceso (aunque, por defecto, están deshabilitados).

¿Rescate de EKS?

Por defecto, el usuario o rol que creó un clúster SIEMPRE tendrá privilegios de administrador sobre el clúster. Y esa es la única forma "segura" de acceso que AWS tendrá sobre el clúster de Kubernetes.

Entonces, si un atacante compromete un clúster usando fargate y elimina a todos los demás administradores y borra al usuario/rol de AWS que creó el clúster, el atacante podría haber rescatado el clústerr.

Ten en cuenta que si el clúster estaba usando EC2 VMs, podría ser posible obtener privilegios de administrador desde el Nodo y recuperar el clúster.

De hecho, si el clúster está usando Fargate, podrías usar nodos EC2 o mover todo a EC2 en el clúster y recuperarlo accediendo a los tokens en el nodo.

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

Otras formas de apoyar a HackTricks:

Última actualización