AWS - EKS Post Exploitation

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

EKS

Για περισσότερες πληροφορίες δείτε

AWS - EKS Enum

Ανίχνευση του cluster από το AWS Console

Εάν έχετε την άδεια eks:AccessKubernetesApi μπορείτε να προβάλετε αντικείμενα Kubernetes μέσω του AWS EKS console (Learn more).

Σύνδεση στο AWS Kubernetes Cluster

  • Εύκολος τρόπος:
# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
  • Όχι τόσο εύκολος τρόπος:

Αν μπορείτε να λάβετε ένα token με aws eks get-token --name <cluster_name> αλλά δεν έχετε δικαιώματα για να πάρετε πληροφορίες του cluster (describeCluster), μπορείτε να ετοιμάσετε το δικό σας ~/.kube/config. Ωστόσο, έχοντας το token, χρειάζεστε ακόμα το url endpoint για να συνδεθείτε (αν καταφέρατε να πάρετε ένα JWT token από ένα pod διαβάστε here) και το όνομα του cluster.

Στην περίπτωσή μου, δεν βρήκα την πληροφορία στα CloudWatch logs, αλλά την βρήκα στα LaunchTemaplates userData και επίσης σε EC2 machines στο userData. Μπορείτε να δείτε αυτή την πληροφορία στο userData εύκολα, για παράδειγμα στο επόμενο παράδειγμα (το όνομα του cluster ήταν 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 ```

Από AWS σε Kubernetes

Ο δημιουργός του EKS cluster είναι ΠΑΝΤΑ σε θέση να εισέλθει στο kubernetes μέρος του cluster ως μέλος της ομάδας system:masters (k8s admin). Τη στιγμή που γράφεται αυτό, δεν υπάρχει άμεσος τρόπος να βρεις ποιος δημιούργησε το cluster (μπορείς να ελέγξεις CloudTrail). Και δεν υπάρχει τρόπος να αφαιρέσεις αυτό το προνόμιο.

Ο τρόπος να παραχωρήσεις πρόσβαση πάνω στο K8s σε περισσότερους AWS IAM users ή roles είναι μέσω του configmap aws-auth.

Warning

Επομένως, οποιοσδήποτε με write access πάνω στο config map aws-auth θα μπορέσει να compromise the whole cluster.

Για περισσότερες πληροφορίες σχετικά με το πώς να grant extra privileges to IAM roles & users στον same or different account και πώς να abuse αυτό, δες privesc check this page.

Δες επίσης this awesome post to learn how the authentication IAM -> Kubernetes work.

Από Kubernetes σε AWS

Είναι δυνατό να επιτραπεί OpenID authentication for kubernetes service account ώστε να μπορούν να assume roles στο AWS. Μάθε πώς this work in this page.

Λήψη Api Server Endpoint από ένα JWT Token

Αποκωδικοποιώντας το JWT token παίρνουμε το cluster id και επίσης την περιοχή. image Γνωρίζοντας ότι το τυπικό format για το EKS url είναι

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

Δεν βρήκα καμία τεκμηρίωση που να εξηγεί τα κριτήρια για τα ‘two chars’ και τον ‘number’. Αλλά κάνοντας μερικά tests από την πλευρά μου βλέπω να επαναλαμβάνονται τα εξής:

  • gr7
  • yl4

Σε κάθε περίπτωση είναι μόνο 3 chars οπότε μπορούμε να τα bruteforce. Χρησιμοποίησε το παρακάτω script για να δημιουργήσεις τη λίστα

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

Στη συνέχεια με wfuzz

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

Warning

Θυμηθείτε να αντικαταστήσετε & .

Παράκαμψη CloudTrail

Αν ένας attacker αποκτήσει διαπιστευτήρια ενός AWS με άδεια πάνω σε ένα EKS. Αν ο attacker ρυθμίσει το δικό του kubeconfig (χωρίς να καλέσει το update-kubeconfig) όπως εξηγήθηκε προηγουμένως, το get-token δεν δημιουργεί logs στο Cloudtrail επειδή δεν αλληλεπιδρά με το AWS API (απλώς δημιουργεί το token τοπικά).

Έτσι, όταν ο attacker επικοινωνεί με το EKS cluster, το cloudtrail δεν θα καταγράψει τίποτα που να σχετίζεται με το κλεμμένο user και την πρόσβασή του.

Σημειώστε ότι το EKS cluster μπορεί να έχει ενεργοποιημένα logs που θα καταγράψουν αυτήν την πρόσβαση (αν και, από προεπιλογή, είναι απενεργοποιημένα).

EKS Λύτρα?

Από προεπιλογή, ο user ή role που δημιούργησε ένα cluster θα έχει ΠΑΝΤΑ δικαιώματα admin πάνω στο cluster. Και αυτή είναι η μόνη «ασφαλής» πρόσβαση που θα έχει το AWS στο Kubernetes cluster.

Έτσι, αν ένας attacker παραβιάσει ένα cluster χρησιμοποιώντας fargate και αφαιρέσει όλους τους άλλους admins και διαγράψει τον AWS user/role που δημιούργησε το Cluster, the attacker could have ransomed the cluster.

Tip

Σημειώστε ότι αν το cluster χρησιμοποιούσε EC2 VMs, μπορεί να είναι δυνατό να αποκτήσετε δικαιώματα Admin από τον Node και να ανακτήσετε το cluster.

Στην πραγματικότητα, αν το cluster χρησιμοποιεί Fargate, μπορείτε να δημιουργήσετε EC2 nodes ή να μεταφέρετε τα πάντα σε EC2 στο cluster και να το ανακτήσετε αποκτώντας πρόσβαση στα tokens στον node.

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks