Escaping to the Node Virtual Machine The first step in the chain was going from container automation scripts run within and accessing the node virtual machine. What they found was there was an allow list of workloads (based on image name and command) that could mount certain host paths.
Specifically a container with an image named
gcr.io.datadoghq/agent* and the command
bash -c could mount (read-only),
/var/run/containerd. This check could by bypassed by providing custom arguments to the container under
args rather than as part of
command. So you control the code
bash will execute inside the datadog image.
As the containerd socket can be mounted inside this image, an attacker can abuse that access to create a new privileged container with full access to the host filesystem. Then, install a systemd service to spawn a reverse shell with full access to the virtual machine including other tenants and their service account tokens and instance metadata. The attacker also gains access to the Kubelet’s credentials.
Full Cluster Takeover
The authors used their tool
sa-hunter to find powerful pods to compromise. Found the
kube-system namespace which is highly privileged (no restrictions) and two pods that are installed by default. So the first step would be to compromise a node virtual machine that is running one of the privileged pods, steal their service account token from the node.
With the service account token one can update an existing deployment’s service account, add a malicious container to the deployment, and read the
Bonus: Invisible Backdoor
A little added bonus to end off the attack, they also document a way of backdooring the system by installing a MutatingAdmissionWebhook which will be called whenever an objects are created or updated in the kubernetes cluster. Giving access to all the pods and secrets and can mutate them. Autopilot admins cannot even list these webhooks and so cannot discover them.