Abusing Roles/ClusterRoles in Kubernetes
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Qui puoi trovare alcune configurazioni di Roles e ClusterRoles potenzialmente pericolose.
Ricorda che puoi ottenere tutte le risorse supportate con kubectl api-resources
Riferendosi all'arte di ottenere accesso a un principale diverso 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:
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.
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.
In RBAC, alcune autorizzazioni comportano rischi significativi:
create
: Concede la possibilità di creare qualsiasi risorsa del cluster, rischiando un'escalation di privilegi.
list
: Consente di elencare tutte le risorse, potenzialmente causando un leak di dati sensibili.
get
: Permette di accedere ai segreti degli account di servizio, costituendo una minaccia per la sicurezza.
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 elevando i privilegi.
Esempio di un pod che ruberà il token del Service Account bootstrap-signer
e lo invierà all'attaccante:
Il seguente 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
Crea il pod con:
One-liner da questo tweet e con alcune aggiunte:
Ora che puoi fuggire verso il nodo, controlla le tecniche post-sfruttamento in:
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 modello precedente:
Privileged + hostPID
Privileged only
hostPath
hostPID
hostNetwork
hostIPC
Puoi trovare esempi di come creare/sfruttare le configurazioni di pod privilegiati precedenti in https://github.com/BishopFox/badPods
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 lo spazio dei nomi di rete host, puoi rubare il ruolo IAM dell'istanza node.
Per ulteriori informazioni controlla:
Pod Escape PrivilegesÈ possibile abusare di questi permessi per creare un nuovo pod e stabilire privilegi come nell'esempio precedente.
Il seguente yaml crea un daemonset e esfiltra il token del SA all'interno del 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 contenitori o ottenere una shell all'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:
Questo permesso 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 ottenere accesso a applicazioni interessanti (come DB) o vulnerabili (web?) all'interno di un pod:
Come indicato in questa ricerca, 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 <pod>
), 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.
Pertanto, un attaccante con accesso in scrittura nella cartella /var/log/ del container potrebbe abusare di questo comportamento in 2 modi:
Modificando il file 0.log
del suo 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:
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://<gateway>:10250/logs/sym/
elencherà il filesystem root dell'host (cambiando il symlink può fornire accesso ai file).
Un laboratorio e un exploit automatizzato possono essere trovati in https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts
Se sei abbastanza fortunato e la capacità altamente privilegiata CAP_SYS_ADMIN
è disponibile, puoi semplicemente rimontare la cartella come rw:
Come indicato in questa ricerca, è possibile bypassare la protezione:
Che doveva prevenire le fughe come quelle precedenti, utilizzando invece di un mount hostPath, un PersistentVolume e un PersistentVolumeClaim per montare una cartella host nel container con accesso in scrittura:
Con un privilegio di impersonificazione dell'utente, un attaccante potrebbe impersonare un account privilegiato.
Basta utilizzare il parametro --as=<username>
nel comando kubectl
per impersonare un utente, o --as-group=<group>
per impersonare un gruppo:
O utilizzare l'API REST:
Il permesso di elencare i segreti potrebbe consentire a un attaccante di leggere effettivamente i segreti accedendo all'endpoint API REST:
Mentre un attaccante in possesso di un token con permessi di lettura richiede il nome esatto del segreto per utilizzarlo, a differenza del più ampio privilegio di elencare i 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 codice sorgente.
Il token è generato da un set limitato di 27 caratteri (bcdfghjklmnpqrstvwxz2456789
), piuttosto che dall'intero intervallo alfanumerico. Questa limitazione riduce il totale delle combinazioni possibili a 14.348.907 (27^5). Di conseguenza, un attaccante potrebbe eseguire un attacco di forza bruta per dedurre il token in poche ore, portando potenzialmente a un'escalation dei privilegi accedendo a account di servizio sensibili.
Se hai i verbi 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, 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 <signerNameDomain>/<signerNamePath>
o <signerNameDomain>/*
Un esempio di un ruolo con tutti i permessi richiesti è:
Quindi, con la nuova CSR del nodo approvata, puoi abuse delle autorizzazioni speciali dei nodi per steal secrets e escalate privileges.
In questo post e questo la configurazione del K8s TLS Bootstrap di GKE è configurata con automatic signing e viene abused per generare credenziali di un nuovo nodo K8s e poi abused 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.
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):
I principi che possono modificare configmaps
nel namespace kube-system su 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:
Puoi usare aws-auth
per la persistenza dando accesso agli utenti di altri account.
Tuttavia, aws --profile other_account eks update-kubeconfig --name <cluster-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.
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).
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.
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.
GCP - Container PrivescIl secondo metodo è assegnare permessi K8s all'interno del cluster identificando l'utente tramite la sua email (inclusi gli account di servizio GCP).
Principi che possono creare TokenRequests (serviceaccounts/token
) quando parlano con l'endpoint API K8s SAs (info da qui).
Principi che possono update
o patch
pods/ephemeralcontainers
possono ottenere esecuzione di codice su altri pod, e potenzialmente uscire al loro nodo aggiungendo un container effimero con un securityContext privilegiato.
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.
Per un esempio di mutatingwebhookconfigurations
, controlla questa sezione di questo post.
Come puoi leggere nella sezione successiva: Prevenzione dell'escalation dei privilegi integrata, 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
su roles
o clusterroles
.
Allora può aggiornare/creare nuovi ruoli, clusterroles con permessi migliori di quelli che ha.
Principi con accesso alla nodes/proxy
subrisorsa possono eseguire codice sui pod tramite l'API Kubelet (secondo questo). Maggiori informazioni sull'autenticazione Kubelet in questa pagina:
Hai un esempio di come ottenere RCE parlando autorizzato a un'API Kubelet qui.
Principi che possono eliminare pod (delete
verbo su pods
risorsa), o espellere 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 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.
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 CVE-2020-8554 previene solo i servizi ExternalIP (secondo questo).
I principi con permessi update
o patch
su nodes/status
o pods/status
, potrebbero modificare le etichette per influenzare i vincoli di programmazione applicati.
Kubernetes ha un meccanismo integrato per prevenire l'escalation dei privilegi.
Questo sistema garantisce che gli utenti non possano elevare i propri privilegi modificando ruoli o binding di ruolo. L'applicazione di questa regola avviene a livello API, fornendo una protezione anche quando l'autenticatore 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 stanno tentando di creare o modificare: o a livello di cluster per ClusterRoles o limitato allo stesso namespace (o a livello di cluster) per i Roles.
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.
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 dare a te stesso o a un diverso SA alcuni privilegi se non li hai 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.
Per impostazione predefinita non c'è alcuna crittografia nella comunicazione tra i pod. Autenticazione reciproca, bidirezionale, da pod a pod.
Crea il tuo .yaml
Modifica il tuo .yaml e aggiungi le righe non commentate:
Vedi i log del proxy:
More info at: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
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.
Se un attaccante riesce in qualche modo a iniettare un Mutationg Admission Controller, sarà in grado di modificare richieste già autenticate. Essere in grado di potenzialmente privesc, e più comunemente persistere nel cluster.
Esempio da https://blog.rewanthtammana.com/creating-malicious-admission-controllers:
Controlla lo stato per vedere se è pronto:
Poi distribuisci un nuovo pod:
Quando puoi vedere l'errore ErrImagePull
, controlla il nome dell'immagine con una delle seguenti query:
Come puoi vedere nell'immagine sopra, abbiamo provato a eseguire l'immagine nginx
, ma l'immagine finale eseguita è rewanthtammana/malicious-image
. Cosa è appena successo!!?
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:
The above snippet replaces the first container image in every pod with rewanthtammana/malicious-image
.
Pod e account di servizio: Per impostazione predefinita, i pod montano un token dell'account di servizio. Per migliorare la sicurezza, Kubernetes consente di disabilitare questa funzionalità di automontaggio.
Come applicare: Imposta automountServiceAccountToken: false
nella configurazione degli account di servizio o dei pod a partire dalla versione 1.6 di Kubernetes.
Inclusione selettiva: Assicurati che solo gli utenti necessari siano inclusi in RoleBindings o ClusterRoleBindings. Esegui audit regolari e rimuovi gli utenti irrilevanti per mantenere una sicurezza rigorosa.
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.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)