Table of contents
No headings in the article.
Welcome to the new blog in the Hack The Box series. Since I am trying to learn more about Kubernetes security, I was looking for a box related to Kubernetes on Hack The Box and found Steamcloud
let us spin up our box, and start the VPN with the OVPN file provided, after getting the IP of the box, let us do a basic Nmap scan on the IP**
Nmap scan gives basic information on open ports and services, let us try to connect with port 8443 in the browser.
Accept the risk and continue,
Forbidden, which we already knew in Nmap scan, by default nmap does not scan all 65,535 ports. So let us try to expand our scanning scope, initially, I tried all ports scanning with all default scripts, but it took much longer than expected, I found a few open ports and then tried to enumerate those with a shorter Nmap script
and found a few open ports, let us try to look up what default services run on these ports. The first port, 2379, says etcd-client; you can guess it as the etcd component comes in the picture. Other running components would be part of Kubernetes architecture (kubelet, API-server). These are pure guesses; let us now search for the Kubernetes pentest guide.
https://cloud.hacktricks.xyz/pentesting-cloud/kubernetes-security
we can see that 10250 is the default port for Kubelet service
let us try to access pods via curl or browser
We can see a list of all pods, but this is only a read-only view, and we won't be able to enumerate much further on this, so let us try to use a new utility called
kubeletctl
You can install kubeletctl using
wget https://github.com/cyberark/kubeletctl/releases/download/v1.9/kubeletctl_linux_amd64 && chmod a+x ./kubeletctl_linux_amd64 && mv ./kubeletctl_linux_amd64 /usr/local/bin/kubeletctl
Reference: https://github.com/cyberark/kubeletctl
As we can see in the examples, let us try to view pods and scan for tokens or RCE using the above commands.
For RCE,
We can see two pods are vulnerable, and we can execute commands on these pods, namely kube-proxy-7fgk4 and nginx pods.
I tried to get a proper reverse shell, but it failed. Enumerating further the directory of the nginx pod, I found various directories and found a user flag.
(Note: This was not the intended way to get a user flag but let us continue further)
Next, we want to get a foothold on the pod as a root user or at least access the root directory to get the root.txt file
Scratching my head, I could think of a way we can do this might be through the shared volumes concept in Kubernetes, the way this works is a volume is created on the host machine and a volumeMount is created on the underlying pod such that the contents, that is the files on pod can be stored on this volume
Let's not get distracted from our goal: to gain access to the file systems on the host machine. To achieve this, we need to find a way to create a pod inside this host machine and use 'hostPath' to mount the host machine's directory onto the pod. I hope this makes sense. I will create a short video at the end to explain it better.
Since we now have access to the initial container, nginx, we can try to obtain the token and CA certificate from this pod. (A service account is always created when starting a pod, so the nginx pod would have a token.)
We can once again use the kubeletctl
utility to scan for tokens.
kubeletctl --server 10.10.11.133 scan token
Using a token of the nginx pod,
echo token="eyJhb..."
Sadly we can't use same technique to get ca certificate, but we can look up for default place where the ca crt is stored in a pod
https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
I am storing this certificate on my machine as a 'ca.crt' file.
Now, let's check what rights we have by using the identity of this service account (using the token and 'ca.crt')
We do have permission to create a new pod using this service account
Great!!!😁
Now using https://kubernetes.io/docs/concepts/storage/volumes/#hostpath , we can create a new pod using the host volume and mount it on the pod
A template file for creating a new pod with host path ⬇️
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
Also, I tried to take a better look at the nginx pod just to have a good view
You can use the above Yaml file or make a few tweaks like I did below
Just make sure to not change the hostPath: path parameter as it specifies that it will mount the whole directories of the host machine on my new pod and all those directories would be available inside /root path of my newly created pod, you can change this to any path you want by changing the mountPath parameter.
Now that we have a yaml/manifest file for our new pod, we can start this pod by following the command
kubectl --server=https://10.10.11.133:8443 --token=$token --certificate-authority=ca.crt get pods
You can see I have 2 failed pods 🫣 , It was my mistake specifying the wrong image name (Confirmed with the error name ImagePullbackOff)
But But we do have a running pod gimme-root-2
, Now let us do the magic to access files of this pod and ultimately view files of the host system
As we have mounted all the files from the host machine to the container gimme-root-2
, we can see from the above command that using ls /root
we can view all directories of the host machine, now we can easily view the user and root flag
This Box was satisfying enough for me to understand Kubernetes misconfigurations and exploits that can be used if hostPath is used 😁🥳🥳