LazyHackers.in — Checklist
📦 Container and Kubernetes Pentest Checklist
Docker + K8s, item by item: scenario · command · steps · the finding · the fix
☰ How to use this guide
Containers and Kubernetes fail in layers: a leaky image (secrets, vulns, root), a dangerous runtime (privileged, host mounts, the Docker socket), a soft orchestrator (over-permissive RBAC, mounted SA tokens, exposed API). The attacker's goal is usually breakout (container → host) then cluster takeover. This guide turns every item into how-to-test. The cloud IAM that backs the cluster is in the Cloud checklist; the app in the container is web/API.
# Image + config scanning (breadth)
trivy image registry/app:tag ; grype registry/app:tag
docker-bench-security ; kube-bench # CIS benchmarks
# Inside-the-pod / cluster recon (assumed breach)
kube-hunter --pod ; amicontained ; kubectl auth can-i --list0 Image security
Images ship secrets in layers, run as root, and carry vulnerable packages. Pull, scan, and inspect the layer history.
trivy image --scanners vuln,secret,config registry/app:tag # vulns + secrets + misconfig
docker history --no-trunc registry/app:tag # secrets baked into layers
docker run --rm -it registry/app:tag id # running as root (uid 0)?
dive registry/app:tag # explore layersImage security — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Secrets in image layers | trivy secret / docker history | Secret in image |
| Image runs as root | docker run ... id | Container runs as root |
| Vulnerable packages (CVE) | trivy/grype | Vulnerable image |
| Outdated/unpinned base image | inspect base | Unpinned base image |
| Unnecessary packages/tools (shell, curl) | inspect image | Bloated attack surface |
| No image signing / provenance | check cosign/notation | Unsigned image |
| Sensitive files in image | dive / find | Sensitive file in image |
1 Dockerfile / build
Build-time misconfigurations: ADD from URLs, secrets in build args, latest tags, and no .dockerignore leaking the repo.
Dockerfile / build — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Secrets in build args/ENV | review Dockerfile | Secret in build |
| ADD with remote URL | review Dockerfile | Unsafe ADD |
| latest / unpinned tag | review FROM | Unpinned image tag |
| No .dockerignore (repo leak) | check context | Build-context leak |
| No USER (root by default) | review Dockerfile | No non-root user |
| Build runs untrusted code | review build steps | Unsafe build step |
2 Container runtime
Runtime flags decide blast radius. Privileged containers, added capabilities, host namespace sharing, and the mounted Docker socket are near-instant host compromise.
# What am I running as / with? (from inside the container)
amicontained # caps, namespaces, seccomp
capsh --print ; cat /proc/1/status | grep CapEff
# The classic: mounted Docker socket = root on host
ls -la /var/run/docker.sock && docker -H unix:///var/run/docker.sock ps
# Host mounts / privileged
mount | grep -E ' / |/host' ; cat /proc/self/status | grep SeccompContainer runtime — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Privileged container | amicontained / inspect | Privileged container |
| Excessive capabilities | capsh --print | Excessive capabilities |
| Docker socket mounted | ls docker.sock | Docker socket exposure |
| Host path mounts (sensitive) | mount | Host filesystem mount |
| Host PID/IPC/network namespace | inspect namespaces | Host namespace sharing |
| Seccomp/AppArmor disabled | check profiles | No syscall/MAC confinement |
| Writable root filesystem | touch /test | Writable root FS |
| No resource limits | inspect limits | No resource limits |
3 Container breakout
Turn a container foothold into host access — via privileged mode, mounts, capabilities (CAP_SYS_ADMIN), the Docker socket, or a runtime CVE.
# Automated breakout enumeration
deepce.sh # or CDK (cdk evaluate / cdk run)
# Docker-socket breakout: launch a host-mounting container
docker -H unix:///var/run/docker.sock run -v /:/host -it alpine chroot /host sh
# Privileged + cgroup release_agent breakout (classic PoC) on vulnerable setupsContainer breakout — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Breakout via privileged mode | deepce/CDK | Container breakout (privileged) |
| Breakout via docker.sock | socket run -v /:/host | Container breakout (socket) |
| Breakout via capability (SYS_ADMIN) | cgroup/release_agent | Container breakout (capability) |
| Breakout via host mount | access mounted host path | Container breakout (mount) |
| Runtime CVE (runc/containerd) | version check | Vulnerable container runtime |
| Kernel exploit from container | kernel version | Host kernel exploitation |
4 Registry security
Registries leak images and secrets when public or weakly authenticated.
Registry security — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Public/anonymous registry | curl /v2/_catalog | Public registry |
| Weak/default registry creds | try defaults | Weak registry credentials |
| Images contain secrets | pull + trivy | Secret in registry image |
| No image signing/verification | check cosign | No image signing |
| No scan on push | review pipeline | No registry scanning |
5 Kubernetes recon
From inside a pod (assumed breach) or with cluster access: what can this identity do, and what's exposed?
# What can the current (pod) identity do?
kubectl auth can-i --list
kubectl auth can-i create pods ; kubectl auth can-i get secrets
# The mounted service-account token (default behaviour)
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# Automated cluster attack tooling
kube-hunter --pod ; peirates ; kdigger dig allKubernetes recon — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Default SA token mounted | cat token | Default SA token mounted |
| Current identity permissions | kubectl auth can-i --list | Permission set mapped |
| Cluster info / version exposed | kubectl version | Cluster fingerprint |
| kube-hunter findings | kube-hunter --pod | Cluster exposure findings |
| Metadata reachable from pod | curl 169.254.169.254 | Cloud metadata from pod |
6 Kubernetes RBAC
Over-permissive RBAC is the road to cluster admin: wildcard verbs/resources, the ability to create pods (then mount a privileged pod), read secrets, or escalate via bind/escalate verbs.
# Find dangerous grants
kubectl get clusterrolebindings,rolebindings -A -o wide
kubectl auth can-i '*' '*' # cluster-admin?
kubectl auth can-i create pods --all-namespaces # -> mount privileged pod -> node
# rbac-tool / rakkess for a permission matrix
rbac-tool analysis ; rakkessRBAC — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Wildcard verbs/resources | rbac-tool / can-i * | Wildcard RBAC |
| create/exec pods (privesc to node) | can-i create pods | Pod-creation escalation |
| get/list secrets | can-i get secrets | Secret-read permission |
| bind/escalate verbs | review roles | RBAC escalation verb |
| cluster-admin binding overused | review bindings | Excessive cluster-admin |
| Anonymous/unauthenticated access | test anon | Anonymous cluster access |
7 Kubernetes secrets
K8s secrets are base64, not encrypted by default; etcd may be unencrypted; and secrets often sit in env vars.
kubectl get secrets -A
kubectl get secret <name> -o jsonpath='{.data.*}' | base64 -d # decode
# Secrets in pod env / configmaps
kubectl get pods -o yaml | grep -iE 'password|token|key'Secrets — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Secrets readable via RBAC | kubectl get secret -o | Readable secrets |
| etcd unencrypted at rest | check encryption config | Unencrypted secrets at rest |
| Secrets in env vars | inspect pod env | Secret in environment |
| Secrets in ConfigMaps | inspect configmaps | Secret in ConfigMap |
| etcd exposed/unauthenticated | probe etcd | etcd exposure |
8 Pod security
Pod specs that allow privileged, hostPath, hostPID/Network, or no securityContext recreate the runtime risks at scale.
Pod security — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Privileged pods allowed | review specs / can-i | Privileged pod allowed |
| hostPath volumes allowed | review specs | hostPath mount allowed |
| hostPID/hostIPC/hostNetwork | review specs | Host namespace pod |
| No securityContext / runAsRoot | review specs | No pod securityContext |
| allowPrivilegeEscalation true | review specs | Privilege escalation allowed |
| No Pod Security Admission / policy engine | check PSA/OPA | No pod-security enforcement |
9 Network policy
Without NetworkPolicies, pods talk to everything — flat east-west, easy lateral movement.
Network policy — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| No NetworkPolicy (flat network) | kubectl get netpol -A | No network segmentation |
| Pod-to-pod unrestricted | reachability test | Unrestricted east-west |
| Metadata reachable from pods | curl metadata | Metadata reachable |
| Sensitive namespace not isolated | reachability test | Namespace isolation gap |
| No mTLS between services | review mesh | No service mTLS |
10 Control-plane exposure
The API server, kubelet and dashboard are crown-jewel endpoints. Anonymous API access, an open read/write kubelet (10250), or an exposed dashboard are cluster takeover.
# Anonymous API access?
curl -sk https://<api>:6443/api/v1/namespaces/kube-system/secrets
# Kubelet read/write API (10250) — exec into pods if open
curl -sk https://<node>:10250/pods
kube-hunter --remote <api-or-node>Control-plane exposure — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| Anonymous API-server access | curl API anon | Anonymous API access |
| Kubelet read/write API open | curl :10250 | Exposed kubelet |
| Dashboard exposed/privileged | probe dashboard | Exposed dashboard |
| etcd exposed | probe :2379 | etcd exposure |
| API server internet-reachable | check exposure | Public API server |
| Control-plane certs weak/old | check certs | Weak control-plane certs |
11 Supply chain & admission control
What gets to run: unsigned images, no admission control, and CI/CD with cluster credentials.
Supply chain & admission — full coverage
| Checklist item | How to test | Report as |
|---|---|---|
| No admission control (OPA/Kyverno) | check controllers | No admission control |
| Unsigned images run | deploy unsigned | Unsigned image admitted |
| CI/CD over-privileged in cluster | review CI SA | Over-privileged CI/CD |
| No pipeline scanning/gating | review pipeline | No supply-chain gating |
| Mutating webhooks abusable | review webhooks | Webhook abuse risk |
✓ Coverage map & how to run it
Work image → runtime → breakout for containers, then the Kubernetes sections for the orchestrator. Benchmark with CIS, verify the escalation chains by hand.
| Section | Run on | Focus |
|---|---|---|
| Image/build 0–1 | Every image | Secrets, root, vulns, Dockerfile |
| Runtime/breakout 2–3 | Every container | Privileged, socket, mounts, breakout |
| Registry 4 | Registries | Exposure, signing |
| K8s 5–11 | Clusters | RBAC, secrets, pod security, network, control plane, supply chain |
Core principle: the chain is image → container → node → cluster. A leaky image plus a dangerous runtime flag is host compromise; over-permissive RBAC or a mounted SA token turns one pod into cluster-admin. Benchmark with CIS (kube-bench/docker-bench) for breadth, but verify the breakout and RBAC escalation paths by hand — and tie findings to blast radius. Tick a box only when you've run the test.