← All Threat Hunting ReportsThreat Hunting Exercise

Threat Hunting Exercise: Analyzing Kubernetes Exec Privileged Pod Dataset

Extending cloud-native coverage with a simulated Kubernetes audit log (k8s_audit_exec_privileged_pod_2022-06-20T151000.json), capturing T1610: Deploy Container and T1611: Escape to Host, where an adversary with stolen or over-permissioned kubectl credentials deploys a privileged pod (or execs into an existing one) to break out of container isolation and access the underlying node's filesystem/credentials.

Step 1: Hypothesis Formation

Hypothesis: An adversary with valid but over-permissioned Kubernetes RBAC access creates a new pod with securityContext.privileged=true and a hostPath volume mount of /, or execs (kubectl exec) into an existing privileged pod, then uses the resulting host-level access to read node secrets (e.g., kubelet credentials, cloud instance metadata) or escape to the underlying host OS. Indicators:

Null Hypothesis: Legitimate privileged workload (e.g., a CNI plugin, storage driver, or monitoring DaemonSet that legitimately requires privileged access) or an authorized debugging session by platform engineering. Invalidate via the requesting identity's RBAC role (should be a human/CI user, not a system: service account) and absence of a change-ticket/known-workload label.

Rationale: Container escape is the Kubernetes analog to the Windows LOLBIN/service-abuse hunts earlier in this series - the audit log's pods and pods/exec resource events are the equivalent of Sysmon Event 1/10, giving us creation and access-context visibility even without host-level EDR inside every container.

Step 2: Data Sources and Scope

Step 3: Key Findings

Parsed audit log (9 events shown) shows a leaked CI service-account token used to deploy a privileged, host-mounted pod, followed by exec access retrieving node-level credentials.

Timestamp (UTC)VerbUserKey DetailsIOC/Why Suspicious?
2022-06-20 15:10:00listsystem:serviceaccount:default:ci-deploy-botresource=pods, namespace=kube-system; sourceIPs=["94.142.241.194"] (external, not the CI runner's known egress range).Recon IOC: Service account token used from an IP outside the CI provider's documented IP range - strong indicator of token theft/reuse.
2022-06-20 15:10:05getsystem:serviceaccount:default:ci-deploy-botresource=secrets, namespace=kube-system.Enumerates cluster secrets - scoping for high-value targets.
2022-06-20 15:10:30createsystem:serviceaccount:default:ci-deploy-botresource=pods; name=debug-tools; namespace=default; spec.containers[0].securityContext.privileged=true; spec.volumes[0].hostPath.path="/".Core IOC: Privileged pod created with the entire host filesystem mounted - the defining container-escape primitive. Name "debug-tools" masquerades as benign tooling.
2022-06-20 15:10:32createsystem:serviceaccount:default:ci-deploy-botobjectRef.subresource=exec; pod=debug-tools; command=["/bin/sh"].Adversary shells into the newly created privileged pod.
2022-06-20 15:10:40(in-pod, Falco)root@debug-toolsFalco alert: "Read sensitive file untrusted" - file=/host/etc/kubernetes/pki/ca.key.Escape IOC: Host filesystem accessed via the hostPath mount from inside the container - cluster CA private key read, enabling full cluster compromise.
2022-06-20 15:10:45(in-pod, Falco)root@debug-toolsFalco alert: "Contact K8S API Server From Container" - outbound to 169.254.169.254 (cloud instance metadata).Credential theft IOC: Container queries the node's cloud instance metadata service - likely harvesting the node's IAM role credentials.
2022-06-20 15:11:10createsystem:serviceaccount:default:ci-deploy-botresource=clusterrolebindings; name=debug-admin-binding; roleRef=cluster-admin; subjects=[ServiceAccount default/ci-deploy-bot].Persistence IOC: Grants the (already-compromised) service account permanent cluster-admin - full RBAC escalation, independent of the original leaked token's original scope.
2022-06-20 15:12:30deletesystem:serviceaccount:default:ci-deploy-botresource=pods; name=debug-tools.Cleanup IOC: Privileged pod deleted post-use - removes the obvious "privileged=true" object from casual kubectl get pods review, though the audit trail and the new clusterrolebinding persist.

Validation:

Step 4: Recommendations & Next Steps

Hypothesis confirmed - container escape via a privileged, host-mounted pod leading to cluster-wide compromise! K8s audit logs plus Falco's in-container visibility together reconstructed a chain that neither source alone would fully capture.