The Machine With Many Faces: Post-Exploitation Identity Misuse in SPIFFE/SPIRE
This research from Palo Alto Unit 42 demonstrates a critical vulnerability in the SPIFFE/SPIRE identity management system for Kubernetes and cloud-native environments. An attacker with root access to a node can exploit this to impersonate co-located workloads by manipulating Linux control group (cgroup) information. The research introduces ‘Spooffe’, a tool to automate this process, highlighting the risk of post-exploitation identity misuse. Organizations should assume root access grants access to all cryptographic identities and implement mitigations such as hardening nodes, restricting root access, and minimizing reliance on weak selectors.
This research from Palo Alto Unit 42 demonstrates a critical vulnerability in the SPIFFE/SPIRE identity management system for Kubernetes and cloud-native environments. An attacker with root access to a node can exploit this to impersonate co-located workloads by manipulating Linux control group (cgroup) information. The research introduces ‘Spooffe’, a tool to automate this process, highlighting the risk of post-exploitation identity misuse. Organizations should assume root access grants access to all cryptographic identities and implement mitigations such as hardening nodes, restricting root access, and minimizing reliance on weak selectors.
SPIFFE (Secure Production Identity Framework for Everyone) and SPIRE (SPIFFE Runtime Environment) are widely deployed to replace long-lived secrets with short-lived, cryptographically verifiable workload identities. These systems rely on a core assumption: that the underlying node is trusted. However, Unit 42 has not observed this technique exploited in the wild.
Researchers discovered that an attacker with root access can spoof the Linux control group (cgroup) information the SPIRE agent uses during workload attestation. This tricks the agent into issuing a co-located workload's SVID (SPIFFE Verifiable Identity Document) to an attacker-controlled process. The tool ‘Spooffe’ is designed to automate this extraction of workload identities (SVIDs).
SPIFFE addresses the ‘Secret Zero’ problem – the challenge of securely introducing the initial secret required to bootstrap trust – by replacing long-lived secrets with short-lived workload identities. When deployed correctly, SPIFFE enforces strong identity boundaries between workloads. Each workload is assigned three identity components: a SPIFFE ID (a URI-style name), an SVID (a short-lived credential), and a Trust Bundle (containing root CA certificates or JSON Web Key Sets).
SPIRE is a production-ready implementation of the SPIFFE specification. The agent performs workload attestation by gathering selectors from the workload process and matching them against cached registration entries. If an entry's selectors are a subset of the workload's selectors, the agent returns the corresponding cached SVID to the workload.
To understand how these identity components are issued and verified in practice, we can now walk through how workload-to-workload identity verification works end to end. When workload A needs to communicate with workload B over mTLS, it requests a short-lived credential from the local SPIRE agent. The agent attests the workload and forwards the attestation data to the SPIFFE server. Based on predefined registration policies, the server selects the appropriate SPIFFE ID for the workload and issues a short-lived X.509 SVID. The server also publishes the corresponding public keys as part of the trust bundle.
Workload attestation is the mechanism directly involved in selector evaluation and the attacks discussed later. Before the agent attests the workloads, the SPIRE server’s administrator must register the workload selectors in the SPIRE server so it can later compare them to the selectors in the agent. In this Kubernetes example, the registration entry authorizes any pod running in the default namespace and using the default service account to receive the specified SPIFFE identity (spiffeID).
The agent periodically synchronizes and caches these registration entries from the server, using them locally during workload attestation to determine which identity applies. The agent generates key pairs for each registration entry, sends certificate signing requests (CSRs) to the server and caches the resulting SVIDs. When a workload wants to authenticate, it requests an SVID (via FetchJWTSVID or FetchX509SVID), connecting to the agent Workload API, typically via a Unix domain socket (such as /run/spire/sockets/agent.sock). The agent then extracts the PID for the calling process. Once the agent receives the PID, it passes it to the configured workload attestor plugins, which collect selectors based on process and container metadata. SPIRE agents support several workload-attestor plugins. Common plugins include docker, k8s, systemd, Unix and Windows. In our cluster, the agent uses the k8s and Unix plugins. The k8s plugin uses the workload PID to access /proc/<pid>/mountinfo or /proc/<pid>/cgroups. It calls GetPodUIDAndContainerID to extract the pod UID and the container ID. In our environment, this process looks like the following: After extracting the container ID and pod UID, the k8s plugin queries the kubelet to retrieve pod metadata. To do this, it uses the SPIRE agent’s service account token, stored at /var/run/secrets/kubernetes.io/serviceaccount/token. The agent's service account has the following permissions, which allow it to list pods and access node information. Using this token, the plugin calls getPodList to retrieve all pods on the node. It then identifies the pod whose UID and container ID match the values extracted from the /proc directory. Once matched, it collects selectors from the pod's metadata: The Unix plugin gathers information from /proc to produce selectors such as user identifier (UID) and group identifier (GID). These selectors are used during workload attestation to bind a workload’s identity to operating system level properties of the calling process, helping SPIRE distinguish between different workloads running on the same node.
