Skip to content

EXPLOIT_HOST_TRAVERSE

Source Destination MITRE
Volume Volume Unsecured Credentials, T1552

This attack represents the ability to steal a K8s API token from a container via access to a mounted parent volume of the /var/lib/kubelet/pods directory.

Details

An attacker in a container with access to the /var/lib/kubelet/pods directory or any parent directory of the node via a hostPath mount, even readonly, can steal the serviceaccount access tokens of all running pods to perform actions in the K8s API.

Prerequisites

A volume containing K8s API tokens is mounted into a container. The canonical case is a node root filesystem mounted readonly via a host path volume mount.

Checks

Check for mounted directories that contain the service account token paths:

# The service account tokens are tmpfs mounts themselves so it is very apparent when they are present
cat /proc/self/mounts

# ...
/dev/vda1 /hostpods ext4 ro,relatime,discard 0 0
tmpfs /hostpods/063c7aae-1965-4824-b4f5-a8e7cdc2d224/volumes/kubernetes.io~projected/kube-api-access-zhzgh tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/648e72af-34a8-4be6-8e7a-9cfac7e7fd94/volumes/kubernetes.io~projected/kube-api-access-hkh28 tmpfs rw,relatime,size=51200k 0 0
tmpfs /hostpods/b8a7238c-83eb-4392-b055-ad08f8b8a218/volumes/kubernetes.io~projected/kube-api-access-xl5fz tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/5edf50d2-747c-45b2-8b40-210f1bfee866/volumes/kubernetes.io~projected/kube-api-access-2l9sx tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/f80874b0-1a52-4175-9705-550b75743adf/volumes/kubernetes.io~projected/kube-api-access-8ms4p tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/2e2811f3-cfb4-41ea-ae51-8e337357e0d0/volumes/kubernetes.io~projected/kube-api-access-7p2hf tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/37d46741-de8b-45b3-a0a4-874529bb4032/volumes/kubernetes.io~projected/kube-api-access-g8wqm tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/05ae5550-ac58-47a3-b466-c09944240062/volumes/kubernetes.io~projected/kube-api-access-pdqmc tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/3a55670f-a784-4d3c-8231-5bf90c54fc87/volumes/kubernetes.io~projected/kube-api-access-2bf8s tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/b40f8657-5a06-49ed-9128-b807de3281e5/volumes/kubernetes.io~projected/kube-api-access-hjbzn tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/4eb7074e-133f-4ecc-8fa4-a686cf46ba6d/volumes/kubernetes.io~projected/kube-api-access-wqsqv tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/23dab617-9d86-4658-823b-12aaab1f0edc/volumes/kubernetes.io~projected/kube-api-access-xd5fl tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/300cbaef-f0aa-441b-b22d-154bfa31901a/volumes/kubernetes.io~projected/kube-api-access-5xwr4 tmpfs rw,relatime,size=15340756k 0 0
tmpfs /hostpods/e949b9f2-304b-4664-93e5-d0ca79d69448/volumes/kubernetes.io~projected/kube-api-access-xrbr4 tmpfs rw,relatime,size=15340756k 0 0
# ...

Exploitation

If all (or part of) the host filesystem is mounted (/host in our example), steal access tokens for ALL pods running on the node:

ls /host/var/lib/kubelet/pods/0dc76586-c18c-4db6-b5f2-019f270d3621
# containers  etc-hosts  plugins    volume-subpaths  volumes

find /host/var/lib/kubelet/pods/ -name token -type l 2>/dev/null
#/host/var/lib/kubelet/pods/5a9fc508-8410-444a-bf63-9f11e5979bee/volumes/kubernetes.io~projected/kube-api-access-225d6/token
#/host/var/lib/kubelet/pods/a1176593-34a2-43e6-8bdd-ed10fa148fe7/volumes/kubernetes.io~projected/kube-api-access-ng6px/token
#/host/var/lib/kubelet/pods/10b90d62-6b16-4aa7-9e72-75f18dcca5a8/volumes/kubernetes.io~projected/kube-api-access-j7dsp/token
#/host/var/lib/kubelet/pods/dfbf38ad-2e92-44e0-b05b-8859350b6ea5/volumes/kubernetes.io~projected/kube-api-access-c89ff/token

See IDENTITY_ASSUME for how to use a captured token.

Defences

Monitoring

  • Monitor for access to well-known K8s secrets paths from unusual processes.

Implement security policies

Use a pod security policy or admission controller to prevent or limit the creation of pods with a hostPath mount of parents of /var/lib/kubelet/pods or other sensitive locations.

Prevent service account token automounting

When a pod is being created, it automatically mounts a service account (the default is default service account in the same namespace). Not every pod needs the ability to access the API from within itself.

From version 1.6+ it is possible to prevent automounting of serviceaccount tokens on pods using:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sa1
automountServiceAccountToken: false

Calculation

References: