Skip to content

Kubernetes Pentesting

Kubernetes (K8s) orchestrates containers at scale, and its security is a world of its own: the surface includes the API server, secrets, RBAC, network policies, pod service accounts, and the possibility of escaping a container to the node (see Container and Docker Escapes). The attacker’s goal is usually to go from “I have access to a pod” to “I control the cluster” (cluster-admin) or the underlying node.

API server the brain: every operation goes through it (port 6443)
etcd the cluster database (includes SECRETS if not encrypted)
kubelet agent on each node (port 10250)
pods containers; each with a service account (mounted token)
RBAC who can do what over which resources
# API exposed? anonymous?
curl -k https://<ip>:6443/version
kubectl get pods --insecure-skip-tls-verify # anonymous access?
# inside a compromised pod: the service account token
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
# exposed kubelet (10250) -> sometimes allows executing in pods

The pod’s mounted service account can usually talk to the API; with its permissions you enumerate and sometimes escalate:

# use the pod's token
export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -k -H "Authorization: Bearer $TOKEN" https://kubernetes.default/api/v1/namespaces/default/pods
# or kubectl if available
kubectl auth can-i --list # what I can do (KEY)
kubectl get secrets -A # can I read secrets? (credentials, tokens)

kubectl auth can-i --list is Kubernetes’s sudo -l: it tells you exactly what your service account allows.

# excessive RBAC
- create pods -> launch a privileged pod mounting the node FS -> node root
- get/list secrets -> steal more privileged SA tokens (including cluster-admin)
- impersonate -> act as another user/SA
- exec in pods -> enter others' pods (lateral)
# container escape (see lin-docker)
- privileged pod / hostPath / hostPID / hostNetwork -> node access
- mount /var/run/docker.sock or the host FS
# unencrypted/unauthenticated etcd -> all cluster secrets
# open kubelet (10250) -> exec in pods without going through the API

Classic example: with permission to create pods, you launch one with hostPath mounting the node’s / → read/write the node filesystem → node root → from there, the cluster.

kubectl # official client (auth can-i, get, exec)
kube-hunter # discovers and tests cluster weaknesses
kubeletctl # abuse the kubelet (10250)
peirates # K8s escalation/pivoting framework
kdigger / BOtB # in-pod enum and escapes
  • Minimal RBAC: no cluster-admin except where essential; no broad create pods/secrets; audit with kubectl auth can-i.
  • Pod Security Standards / admission controllers (OPA/Gatekeeper, Kyverno): forbid privileged pods, hostPath, hostPID.
  • Encrypted etcd secrets (encryption at rest) and external manager; network policies (segment pods).
  • Non-anonymous API server, authenticated kubelet (no open 10250), don’t mount docker.sock or the host FS.
  • API server logging/auditing; image scanning; automountServiceAccountToken: false where unused.
  • Is the API server (6443) or kubelet (10250) exposed/anonymous?
  • Pod service account token and auth can-i --list
  • get/list secrets → steal privileged tokens
  • create pods → privileged pod/hostPath → node
  • exec/impersonate for lateral/escalation
  • Container escape to the node (Container and Docker Escapes)
  • Unencrypted etcd → cluster secrets
  • Map up to cluster-admin or node root