Hacking Kubernetes via ServiceAccountTokens

Kubernetes has a large amount of advancements and inherent good security principles but these are dependent on configurations that are typically not well-known to end users. Predominantly the constructs of Service Accounts or (Non-human Identities) for the masses are populated in many services as they act as the go-between for service to authenticate and operate in the background. When a user deploys a pod which can be one container or multiple containers that configuration should ideally be checked prior to authorization for known weaknesses such as automountServiceAccountToken. When this isn’t checked the end user whether this is a Kubernetes administrator or other if able to access the underlying pod can use this token to access other methods that the Pod has permissions to.

Getting Started

Given I’ve been on and off preparing for a renewal of Certified Kubernetes Security specialist this specific exam led me to create my own scenarios from researching and creating my own tool Paranoia (KSPM) to demonstrate some methods to help others. Additionally this is just a net new project that I’ve started uploading scenarios to in Github and will grow to encompass some new topics such as the BOM/SBOM and uses of Falco as well.

  • Kubernetes 1.32 (or local cluster KiND, etc)
  • Scenarios deployed (repository shown)

We start with the following command to grab our code

git clone https://github.com/sn0rlaxlife/cks-scenarios.git
cd cks-scenarios/scenario_1

We should see the following annotated in here running a ‘ls’ command

- Readme.MD
- scenario.sh (our scenario)
- validate.sh (Validation of task)

To execute this on our cluster I just run a chmod +x as shown below

chmod +x scenario.sh validate.sh

Deploy our scenario running the following then we can dissect what is deployed.

./scenario.sh

So we’ve deployed three pods insecure-pod, explicit-insecure-pod, secure-pod along with some service accounts and in its all hosted in our namespace cks-training.

k get pods -n cks-training -o yaml | grep automountServiceAccountToken

This is one method to stream-line against our output what this value is set to so we can identify our method to exfiltrate.

We can see it picks up explicit-insecure-pod as true for this parameter this means the associated ServiceAccount token is mounted on the pod itself. Now we have a method to check our pod for existence of the token is it accessible?

Before we go about that method let’s see if the explicit-insecure-pod has a serviceAccount attached to it and if it has roles, role binding associated.

k get pods -n cks-training -o yaml | grep serviceAccount

So we can see we have the following service accounts assigned as secure-sa, insecure-sa this is our starting point we should see if any permissions are associated with the two service accounts.

We inspect the first secure-sa with the following command.

k get sa secure-sa -n cks-training -o yaml

We can see this specific service account has the explicit flag set to False so its less likely to be susceptible since this won’t grant the pod the token however lets investigate the insecure-sa.

k get sa insecure-sa -n cks-training -o yaml

This looks like the best method to pursue as the automountServiceAccountToken isn’t defined and we also saw in our previous screenshot that this is set to true.

In the task we are trying to exfiltrate secrets defined in the sensitive-data from the pod and store them in the pod that this is able to happen in the /tmp/exercise-completed/password.txt – /tmp/exercise-completed/api-key.txt.

First we execute into the pod that is explicit-insecure-pod and try out our method and see first if we can access the token.

k exec -it explicit-insecure-pod -n cks-training -- ls -la /var/run/secrets/kubernetes.io/serviceaccount/

So we can see from this we can see data/token now let’s try to access this and see if we can use as a Bearer Token for a request for our secrets.

k exec -it explicit-insecure-pod -n cks-training -- sh

(This will show)
# KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

# curl -s https://kubernetes.default.svc/api/v1/namespaces/cks-training/secrets \
 -H "Authorization: Bearer $KUBE_TOKEN" -k

This will return given the secure-sa that is associated with the pod itself doesn’t have access to the resource.

Let’s repeat the same steps in insecure-pod and see what happens.

First, we check for the existence of the token is accessible via the shell.

Running the same command our response is accepted and inside the pod we can access the secrets associated with the namespace.

This can now be accessed by the shell inside the pod we have to now decode the secret if you recall these are in base64 and we have to store the flag as the following.

cd tmp
/tmp -> mkdir exercise-completed
echo <data> | base64 -d > /tmp/exercise-completed/api-key.txt

echo <data> | base64 -d > /tmp/exercise-completed/password.txt

Next we run our validation script that checks if we are correct and exact values are extracted.

./validate.sh

This should return if all is correct the following view to the end-user.

Summary

In Kubernetes, the automountServiceAccountToken setting determines whether a pod automatically receives a service account token, granting it access to the cluster API. This can introduce security risks when misconfigured, potentially leading to unauthorized access as shown in this blog post. This blog post is meant to demonstrate step-by-step scenario showing how an attacker could exploit a misconfigured pod with automountServiceAccountToken: true to access and exfiltrate secrets from the cluster. Ensure when you are running your cluster you are aware of methods to prevent automountServiceAccountToken parameters that don’t require API access this can typically be intercepted with OPA Gatekeeper. Keep a close eye on service account activity in clusters as these are typically leveraged as a method of attack paths. As a clean up remember to delete your configuration by simply removing the namespace or delete the cluster that is being used for testing to remove any of the configuration.