Files

10 KiB

AWS - EKS Post Exploitation

{{#include ../../../../banners/hacktricks-training.md}}

EKS

Per ulteriori informazioni controlla

{{#ref}} ../../aws-services/aws-eks-enum.md {{#endref}}

Enumerate the cluster from the AWS Console

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

Connect to AWS Kubernetes Cluster

  • Easy way:
# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
  • Not that easy way:

If you can ottenere un token with aws eks get-token --name <cluster_name> but you don't have permissions to get cluster info (describeCluster), you could preparare il tuo ~/.kube/config. However, having the token, you still need the url endpoint to connect to (if you managed to get a JWT token from a pod read here) and the name of the cluster.

In my case, I didn't find the info in CloudWatch logs, but I found it in LaunchTemaplates userData and in EC2 machines in userData also. You can see this info in userData easily, for example in the next example (the cluster name was 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 ```

Da AWS a Kubernetes

Storicamente, il creator di un EKS cluster riceveva un accesso admin nascosto a Kubernetes che non era visibile in aws-auth. Negli attuali EKS clusters, questo dipende dalla cluster access configuration. bootstrapClusterCreatorAdminPermissions controlla se il creator viene aggiunto come cluster-admin access entry durante la creazione, e gli EKS access entries rendono questo percorso admin visibile e revocabile tramite la EKS API. I cluster più vecchi o i cluster che si basano ancora su aws-auth potrebbero avere ancora il comportamento legacy del creator, quindi verifica accessConfig, elenca gli access entries e controlla CloudTrail invece di assumere che il creator abbia sempre system:masters non rimovibile.

Abusing configmap

Il modo tradizionale per concedere accesso over K8s a più AWS IAM users o roles è usare il configmap aws-auth.

Warning

Pertanto, chiunque abbia write access sul config map aws-auth potrà compromettere l'intero cluster.

Per maggiori informazioni su come concedere privilegi extra a IAM roles & users nello stesso o diverso account e su come abuse questo per privesc check this page.

Controlla anche this awesome post per imparare come funziona l'autenticazione IAM -> Kubernetes.

Abusing Access Entries

AWS implementa un modo aggiuntivo per concedere agli IAM users accesso al Kubernetes cluster tramite access entries. Se hai i permessi eks:CreateAccessEntry e eks:AssociateAccessPolicy, potresti anche essere in grado di assegnare un ruolo da amministratore Kubernetes al tuo user o a un role specifico.

Per prima cosa, crea un access entry per il tuo user o role:

aws eks create-access-entry --cluster-name <cluster_name> --region <region> --principal-arn <arn_from_your_user_or_role> --type STANDARD

Con quella voce creata, ora potresti essere in grado di assegnargli direttamente una policy. Esiste una policy AWS integrata chiamata AmazonEKSClusterAdminPolicy che può essere usata direttamente. Tieni presente che, se il tuo ambiente ha altre custom policies che concedono anche privilegi elevati in EKS, puoi cambiare --policy-arn con una qualsiasi di quelle:

aws eks associate-access-policy --cluster-name <cluster_name> --region <region> --principal-arn <arn_from_your_user_or_role> --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster

Puoi cercare questa policy nella documentazione ufficiale di AWS qui

Da questo momento in poi, potresti ora essere in grado di richiedere un token k8s e interagire con il cluster come amministratore:

aws eks get-token --cluster-name <cluster_name> --output json | jq -r '.status.token'

Da Kubernetes ad AWS

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

GET Api Server Endpoint from a JWT Token

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

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

Non ho trovato alcuna documentazione che spieghi i criteri per i "due chars" e il "number". Però facendo alcuni test da parte mia vedo che ricorrono questi:

  • gr7
  • yl4

In ogni caso sono solo 3 chars, possiamo bruteforzarli. Usa lo script qui sotto per generare 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))

Poi con wfuzz

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

Warning

Remember to replace & .

Bypass CloudTrail

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

Quindi quando l'attacker parla 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, l'user o role che ha creato un cluster avrà SEMPRE privilegi admin sul cluster. Ed è l'unico accesso "secure" che AWS avrà sul cluster Kubernetes.

Quindi, se un attacker compromette un cluster usando fargate e rimuove tutti gli altri admin ed elimina l'utente/role AWS che ha creato il Cluster, l'attacker potrebbe aver riscattato il clusterr.

Tip

Nota che se il cluster stava usando EC2 VMs, potrebbe essere possibile ottenere privilegi Admin dal Node e recuperare il cluster.

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

{{#include ../../../../banners/hacktricks-training.md}}