AWS - EKS Post Exploitation

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

EKS

Para más información consulta

AWS - 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 (Learn more).

Conectar al clúster de Kubernetes de AWS

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

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

En mi caso, no encontré la información en los logs de CloudWatch, pero la encontré en LaunchTemaplates userData y también en las máquinas EC2 en userData. Puedes ver esta información en userData fácilmente, por ejemplo en el siguiente ejemplo (el nombre del cluster 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
kube config ```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 ```

From AWS to Kubernetes

El creador del EKS cluster va a poder SIEMPRE acceder a la parte de kubernetes del grupo system:masters (admin k8s). Al momento de escribir esto no hay manera directa de saber quién creó el cluster (puedes revisar CloudTrail). Y no hay forma de eliminar ese privilegio.

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

Warning

Por lo tanto, cualquiera con acceso de escritura sobre el config map aws-auth podrá comprometer todo el cluster.

Para más información sobre cómo conceder privilegios extra a IAM roles & users en la misma o diferente cuenta y cómo abusar de esto para privesc revisa esta página.

Check also este excelente post para aprender cómo funciona la autenticación IAM -> Kubernetes.

From Kubernetes to AWS

Es posible permitir una autenticación OpenID para kubernetes service account para permitirles asumir roles en AWS. Aprende cómo esto funciona en esta página.

GET Api Server Endpoint from a JWT Token

Al decodificar el token JWT obtenemos el cluster id y también la región. image Sabiendo que el formato estándar para la url de EKS es

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 haciendo algunas pruebas por mi parte veo que se repiten estos:

  • gr7
  • yl4

De todas formas son solo 3 caracteres; podemos bruteforcearlos. Usa 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))

Luego con wfuzz

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

Warning

Recuerda reemplazar & .

Bypass CloudTrail

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

Así que cuando el attacker se comunica con el EKS cluster, cloudtrail no registrará nada relacionado con el user robado y su acceso.

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

¿Rescate en EKS?

Por defecto, el user o role que creó un cluster va a tener SIEMPRE admin privileges sobre el cluster. Y ese es el único acceso “seguro” que AWS tendrá sobre el Kubernetes cluster.

Entonces, si un attacker compromete un cluster usando fargate y elimina a todos los otros admins y elimina el AWS user/role que creó el Cluster, el attacker podría haber exigido un rescate al cluster.

Tip

Ten en cuenta que si el cluster estaba usando EC2 VMs, podría ser posible obtener Admin privileges desde el Node y recuperar el cluster.

De hecho, si el cluster está usando Fargate podrías añadir EC2 nodes o mover todo a EC2 en el cluster y recuperarlo accediendo a los tokens en el node.

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks