AWS - EKS Post Exploitation

Reading time: 6 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

EKS

Per ulteriori informazioni controlla

AWS - EKS Enum

Enumerare il cluster dalla Console AWS

Se hai il permesso eks:AccessKubernetesApi puoi visualizzare gli oggetti Kubernetes tramite la console AWS EKS (Learn more).

Connettersi al Cluster Kubernetes di AWS

  • Modo semplice:
bash
# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
  • Non è così facile:

Se puoi ottenere un token con aws eks get-token --name <cluster_name> ma non hai i permessi per ottenere informazioni sul cluster (describeCluster), potresti preparare il tuo ~/.kube/config. Tuttavia, avendo il token, hai ancora bisogno dell'url endpoint a cui connetterti (se sei riuscito a ottenere un token JWT da un pod leggi qui) e del nome del cluster.

Nel mio caso, non ho trovato le informazioni nei log di CloudWatch, ma le ho trovate in LaunchTemplates userData e in macchine EC2 in userData anche. Puoi vedere queste informazioni in userData facilmente, ad esempio nel seguente esempio (il nome del cluster era cluster-name):

bash
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:<acc-id>:cluster/<cluster-name>
contexts:
- context:
cluster: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
user: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
current-context: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
kind: Config
preferences: {}
users:
- name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- --region
- us-west-2
- --profile
- <profile>
- eks
- get-token
- --cluster-name
- <cluster-name>
command: aws
env: null
interactiveMode: IfAvailable
provideClusterInfo: false

Da AWS a Kubernetes

Il creatore del cluster EKS sarà SEMPR in grado di accedere alla parte del cluster kubernetes del gruppo system:masters (admin k8s). Al momento della scrittura non c'è modo diretto per scoprire chi ha creato il cluster (puoi controllare CloudTrail). E non c'è modo di rimuovere quel privilegio.

Il modo per concedere accesso a più utenti o ruoli AWS IAM su K8s è utilizzare il configmap aws-auth.

warning

Pertanto, chiunque abbia accesso in scrittura sul config map aws-auth sarà in grado di compromettere l'intero cluster.

Per ulteriori informazioni su come concedere privilegi extra a ruoli e utenti IAM nello stesso o diverso account e come abusare di questo per privesc controlla questa pagina.

Controlla anche questo fantastico post per imparare come funziona l'autenticazione IAM -> Kubernetes.

Da Kubernetes a AWS

È possibile consentire un autenticazione OpenID per l'account di servizio kubernetes per consentire loro di assumere ruoli in AWS. Scopri come questo funziona in questa pagina.

OTTIENI l'Endpoint del Server Api da un Token JWT

Decodificando il token JWT otteniamo l'id del cluster e anche la regione. image Sapendo che il formato standard per l'url EKS è

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

Non ho trovato alcuna documentazione che spieghi i criteri per i 'due caratteri' e il 'numero'. Ma facendo alcuni test per conto mio vedo che ricorrono questi:

  • gr7
  • yl4

Comunque sono solo 3 caratteri che possiamo bruteforzare. Usa lo script qui sotto per generare la lista.

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

Poi con wfuzz

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

warning

Ricorda di sostituire & .

Bypass CloudTrail

Se un attaccante ottiene le credenziali di un AWS con permessi su un EKS. Se l'attaccante configura il proprio kubeconfig (senza chiamare update-kubeconfig) come spiegato in precedenza, il get-token non genera log in Cloudtrail perché non interagisce con l'API AWS (crea solo il token localmente).

Quindi, quando l'attaccante comunica con il cluster EKS, cloudtrail non registrerà nulla relativo all'utente rubato e al suo accesso.

Nota che il cluster EKS potrebbe avere i log abilitati che registreranno questo accesso (anche se, per impostazione predefinita, sono disabilitati).

EKS Ransom?

Per impostazione predefinita, il utente o il ruolo che ha creato un cluster ha SEMPRE privilegi di amministratore sul cluster. E che l'unico accesso "sicuro" che AWS avrà sul cluster Kubernetes.

Quindi, se un attaccante compromette un cluster utilizzando fargate e rimuove tutti gli altri amministratori e elimina l'utente/ruolo AWS che ha creato il Cluster, l'attaccante potrebbe aver riscattato il clusterr.

tip

Nota che se il cluster stava utilizzando EC2 VMs, potrebbe essere possibile ottenere privilegi di amministratore dal Node e recuperare il cluster.

In realtà, se il cluster utilizza Fargate, potresti utilizzare nodi EC2 o spostare tutto su EC2 nel cluster e recuperarlo accedendo ai token nel nodo.

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks