AWS - EKS Post Exploitation

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

EKS

Aby uzyskać więcej informacji, zobacz

AWS - EKS Enum

Enumerate the cluster from the AWS Console

Jeśli masz uprawnienie eks:AccessKubernetesApi, możesz view Kubernetes objects przez AWS EKS console (Learn more).

Połącz z klastrem AWS Kubernetes

  • Najprostszy sposób:
# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
  • Nie taka łatwa metoda:

Jeśli możesz uzyskać token przy pomocy aws eks get-token --name <cluster_name>, ale nie masz uprawnień do pobrania informacji o klastrze (describeCluster), możesz przygotować własny ~/.kube/config. Jednak mając token, nadal potrzebujesz endpointu URL, z którym się połączyć (jeśli udało ci się uzyskać token JWT z poda przeczytaj here) oraz nazwy klastra.

W moim przypadku nie znalazłem tej informacji w logach CloudWatch, ale znalazłem ją w LaunchTemaplates userData oraz również w userData maszyn EC2. Te informacje można łatwo zobaczyć w userData, na przykład w poniższym przykładzie (nazwa klastra to 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 ```

Z AWS do Kubernetes

The creator of the EKS cluster is ALWAYS going to be able to get into the kubernetes cluster part of the group system:masters (k8s admin). At the time of this writing there is no direct way to find who created the cluster (you can check CloudTrail). I nie ma sposobu na usunięcie tego uprawnienia.

The way to grant access to over K8s to more AWS IAM users or roles is using the configmap aws-auth.

Warning

Therefore, anyone with write access over the config map aws-auth will be able to compromise the whole cluster.

For more information about how to grant extra privileges to IAM roles & users in the same or different account and how to abuse this to privesc check this page.

Check also this awesome post to learn how the authentication IAM -> Kubernetes work.

Z Kubernetes do AWS

It’s possible to allow an OpenID authentication for kubernetes service account to allow them to assume roles in AWS. Learn how this work in this page.

Uzyskanie Api Server Endpoint z JWT Token

Dekodując JWT token otrzymujemy id klastra oraz region. image Znając, że standardowy format URL dla EKS to

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

Nie znalazłem dokumentacji wyjaśniającej kryteria dla ‘dwóch znaków’ i ‘liczby’. Jednak przeprowadzając własne testy zauważyłem powtarzalność następujących:

  • gr7
  • yl4

W każdym razie to tylko 3 znaki, więc możemy je bruteforce’ować. Użyj poniższego skryptu do wygenerowania listy

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

Następnie za pomocą wfuzz

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

Warning

Pamiętaj, aby zastąpić & .

Obejście CloudTrail

Jeśli atakujący uzyska poświadczenia AWS z uprawnieniami do EKS. Jeśli atakujący skonfiguruje własny kubeconfig (bez wywoływania update-kubeconfig), jak wyjaśniono wcześniej, get-token nie generuje logów w Cloudtrail, ponieważ nie komunikuje się z API AWS (token jest tworzony lokalnie).

Więc gdy atakujący komunikuje się z klastrem EKS, cloudtrail nie zarejestruje niczego związanego z przejęciem użytkownika i jego dostępem.

Zwróć uwagę, że klaster EKS może mieć włączone logi, które zarejestrują ten dostęp (choć domyślnie są wyłączone).

EKS — szantaż?

Domyślnie użytkownik lub rola, która utworzyła klaster ZAWSZE będzie miała uprawnienia administratora do klastra. I jest to jedyny “bezpieczny” dostęp, jaki AWS ma nad klastrem Kubernetes.

Zatem, jeśli atakujący przejmie klaster używając fargate i usunie wszystkich pozostałych administratorów i usuwa użytkownika/rolę AWS, która utworzyła klaster, atakujący mógłby zaszantażować klaster.

Tip

Zauważ, że jeśli klaster używał EC2 VMs, możliwe jest uzyskanie uprawnień administratora z Node i odzyskanie klastra.

W praktyce, jeśli klaster używa Fargate, możesz utworzyć EC2 nodes albo przenieść wszystko na EC2 w klastrze i odzyskać go, uzyskując dostęp do tokenów na nodzie.

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks