Back again with a TryHackMe CTF writeup! This CTF is a medium level challenge hosted on TryHackMe. This challenge emphasizes the exploitation of an insecure kubernetes configuration. Before completing this CTF, I was somewhat familiar with what kubernetes is, but I really was not familiar at all with any possible kubernetes vulnerabilities and the techniques to exploit those vulnerabilities. I do need to continue to learn more about kubernetes, as it is a fairly widespread platform.
Frank & Herby Make an App is linked here: https://tryhackme.com/room/frankandherby
Initial Scans & Enumeration
First, we need to run a port scan against the target IP address. Doing so gives us quite a bit of output. I took screenshots of the entire nmap ouput, but six screenshots will take up a lot of space, and isn’t totally necessary. To sum up the nmap output, the target machine is exposing the following ports:
22, 3000, 10250, 10255, 10257, 10259, 16443, 25000, 31337, 32000
Other than port 22 (SSH), most of these ports clearly had something to do with kubernetes. Port 31337 in particular, serves clients a website which appears to be pretty much an empty template.
From here, it would be a good idea to run a directory bruteforce tool like dirsearch or gobuster. I ran dirsearch using the dirsearch.txt wordlist from seclists. The command goes like this: dirsearch -e aspx,txt,rar,zip,pdf,png,jpg,zip,pdf,js,py,sh -w /usr/share/seclists/Discovery/Web-Content/dirsearch.txt -t 60 -u http://<targetIP>:31337
/.git-credentials sounds pretty interesting, lets take a look. We can enter “http://<targetIP>:31337/.git-credentials”. This will present us a prompt to download a file. Download the file and view it’s contents.
The file gives us some credentials in an odd format and which seem to be URL encoded. We can use the cyberchef tool to decode it, giving us the actual credentials in plaintext. I explored some of the different ports from the nmap scan, looking for somewhere to use these credentials. Lucky for us, we can use the credentials to get an SSH session!
We can now list the current directory contents with the ls command, and we see the user.txt flag. Cat out the flag!
The first thing I decided to from here was check for sudo permissions by using “sudo -l”. Unfortunately, Frank does not have sudo privileges. I also checked for any binaries with the SUID bit set, but nothing would escalate us to root. Then I remembered seeing microk8s mentioned in the SSH welcome message. Always pay attention to the welcome message when you are able to get an SSH session! Sometimes it can reveal valuable information. Doing some googling, we see that microk8s is a lightweight kubernetes distribution often used in IoT and edge devices. Our googling also leads us to some guidance on how we can exploit microk8s to escalate our privileges to root. Basically, members of the microk8s group can escalate privileges to root by provisioning a new container which mounts to the host filesystem. After doing this, we should be able to access the entire filesystem and get the root flag. The link here explains the process, and can guide you through the process like it did me. Since frank is in fact a member of the microk8s group, we can use the aforementioned method to escalate our privileges. First we need to see what pods we have available to work with on the target system by using the kubectl command “microk8s kubectl get pods”, revealing one running pod that we can use (nginx-deployment-7b548976fd-77v4r). Now we need to get the properties of the pod by using the command “microk8s kubectl get pod nginx-deployment-7b548976fd-77v4r -o yaml”. This reveals an image that we can use at localhost:32000/bsnginx. Referencing the pulsesecurity article I linked earlier, I changed the “image” key to localhost:32000/bsnginx, and kept everything else the same as it is specified in the article. Then I saved the settings as a yaml file (pod.yaml) from my text editor. From here, I used a python HTTP server to serve the yaml file to the target. Back on the target machine we can use wget to download the yaml file, and then use the yaml file to configure the new pod definition with the command “microk8s kubectl apply -f pod.yaml”. Now we are able to spin up a shell session in the new container with “microk8s kubectl exec -it hostmount /bin/bash”. Now with this session, we can cd into the /mnt/root directory and retrieve the root flag!
Conclusion & Takeaways
This was a really interesting and fun CTF for me. I learned a good amount of new things about kubernetes and microk8s throughout the completion of it, and the additional research I did afterwards. As I said earlier, I definitely intend to continue learning more about kubernetes and its security implications, vulnerabilities, etc.
I hope you enjoyed this writeup and got some value from it, and I hope you come back to read some more writeups/blog posts in the future as well. Thank you!