Kubetier
← Permission Reference
T1

create cronjobs

CronJobs give recurring pod execution with the same escalation paths as pod creation, plus persistent code execution that survives pod restarts, a self-healing backdoor.

Contextual upgrade to T0:

T0 where the target namespace holds a cluster-privileged ServiceAccount, because serviceAccountName is chosen freely and the schedule executes the pod with no further access needed. kube-system is the common case.

Elsewhere this is a foothold in the namespace rather than cluster compromise.

API Group
batch
Scope
namespaced
Audit Level
Request

Escalation Paths

  1. Create a pod with privileged + hostPID or hostPath mounting /

  2. Set spec.nodeName to a specific control plane node to force placement there.

    The NoSchedule taint kubeadm puts on those nodes is a scheduler check only, so a directly bound pod needs no toleration

  3. chroot or nsenter into the host to gain root on the node

  4. Read /etc/kubernetes/pki, steal kubelet cert or SA tokens.

    This is T0 on the control plane

Additional rights needed:

none
K8s docs ↗
  1. Create a workload with serviceAccountName set to a privileged ServiceAccount in the same namespace.

    Any controller-backed kind works, since the controller creates the pod.

  2. The token is mounted at /var/run/secrets/kubernetes.io/serviceaccount/token, or projected explicitly by the manifest.

  3. Reading it back needs a channel, and the cheapest costs no RBAC at all: the container sends the token outbound itself.

    This is why removing pods/log does not close the path.

  4. With get on pods/log, the container prints the token to stdout and the attacker reads it back.

  5. With get on pods, the container writes the token to /dev/termination-log and the attacker reads terminated.message from the pod's status, with no pods/log needed.

  6. Authenticate as the ServiceAccount with the stolen token.

Additional rights needed:

none
K8s docs ↗

See Also

K8s docs ↗