Obscurity is medium difficulty Linux machine that features a custom web server. A code injection vulnerability is exploited to gain an initial foothold as www-data . Weak folder permissions reveal a custom cryptography algorithm, that has been used to encrypt the user's password. A known plaintext attack reveals the encryption key, which is used to decrypt the password. This password is used to move laterally to the user robert , who is allowed to run a faux terminal as root. This can be used to escalate privileges to root via winning a race condition or by overwriting sudo arguments.
Reconnaissance
There are two open ports and two closed ports. SSH service running on port 22 seems normal and an interesting HTTP service on port 8080 running a BadHTTPServer.
Checking out the page of port 8080 will greet us with quoted 3 words.
Scrolling down to the bottom of the page will lead us to some interesting information.
The domain name for this box is obscure.htb and not the typical machine.htb format like obscurity.htb.
The file name SuperSecureServer.py is hidden in an unknown directory.
I decided to use wfuzz to brute force the hidden directory using a compiled list of words from the webpage.
After running the tool, I quickly found the hidden directory.
Reading and analyzing the source code in the serveDoc() function will lead us to these code lines with comments.
info = "output = 'Document: {}'" # Keep the output for later debug
exec(info.format(path)) # This is how you do string formatting, right?
The python script uses a dangerous exec()statement that allows users to input commands directly into the command line. But before that, we need to escape the value of info variable to execute commands.
The value of info variable is output = 'Document: {}' and we can escape it by appending '; followed by a command and a # to comment the following characters.
Bypass: output = 'Document: ';<command_here>#
Requesting the following in cURL with the payload below will help us pop a shell.
Entering to Robert's home will greet us with many files.
Since I have no permission to read the user.txt file as www-data, I have to check each files inside his home.
The check.txt file contains a message: Encrypting this file with your key should result in out.txt, make sure your key is correct!
The out.txt file contains encrypted message that seems to be encrypted by the python script: ¦ÚÈêÚÞØÛÝÝ×ÐÊßÞÊÚÉæßÝËÚÛÚêÙÉëéÑÒÝÍÐêÆáÙÞãÒÑÐáÙ¦ÕæØãÊÎÍßÚêÆÝáäèÎÍÚÎëÑÓäáÛÌ×v
The content of passwordreminder.txt is also encrypted: ÑÈÌÉàÙÁÑ鯷¿k which might be useful in authenticating as Robert.
So the encrypted content of out.txt could possibly contain something useful and vital to decrypt the content of passwordreminder.txt. The objective is clear, to get the key.
The last file to check is the script written in python SuperSecureCrypt.py which could give us a detailed information on how the creator encrypts the out.txt and passwordreminder.txt files.
Reading and analyzing the python script tells us that we can use it to encrypt plaintext and decrypt cipher text. Also, both function seems to be using a substitution cipher called Vigenère cipher.
For the Encryption, the plaintext(P) and key(K) are added modulo 255. Ci = (Pi + Ki) mod 255
For the Decryption, the cipher text(C) are subtracted to key(k) module 255. Pi = (Ci - Ki) mod 255
If we go back to the given script and check the decrypt function, we see that it operates by subtracting the key from the cipher text to return the plaintext.
Using the same script, we can do the following formula: Ki = (Ci - Pi) mod 255. We can use the plaintext(P) as the key(k) and subtract it to the cipher text(c) to get the key(k).
So the command to get the key would be:
Result is alexandrovichalexandrovichalexandrovichalexandrovichalexandrovichalexandrovichalexandrovich
As I've mentioned, the encryption process is a simple substitution cipher only using the Vigenère cipher and the key used to encrypt the content of out.txt file is: alexandrovich.
Now, we can use it to decrypt the content of passwordreminder.txt.
Password is SecThruObsFTW and we can now use it to authenticate as Robert.
Rooting the Machine
Going back to robert's directory, we noticed that there's a folder called BetterSSH, and running the sudo -l command tells us that we can run BetterSSH.py as root.
Accessing the BetterSSH.py will give us the following source code.
The python script allows us to authenticate and interact with /etc/shadow file. If the credential provided is existed, it will just authenticate and permit us to run commands with sudo, but if not, it will create a user in a temporary file.
So the first thing I did is to create a bash file that will add robert as sudoer.
Then I simply run sudo /usr/bin/python3 /home/robert/BetterSSH/BetterSSH.py and entered robert's credential.
As I said, once authenticated, we can easily run command in sudo.
Fortunately, there's a vulnerability in the code that allows us to pollute the -u option/argument of the sudo command.
Normally, if you run whoami it will be executed as sudo -u robert whoami and the output would be robert.
But if we run -u root whoami it will be executed as a sudo -u robert -u root whoami and the output would be root.
Running the command -u root /bin/bash make_robert_as_sudoer.sh will add Robert as sudoer.
Since I'm done running the python script and making robert as sudoer, just re-authenticate as Robert then run sudo -i, enter the password and you're root.
Takeaways
Review and configure the permission of the file to restrict external users from accessing it especially if it's for dev environment.
If possible, avoid using eval and exec in your source code to prevent command injection.
Conduct source code review to spot vulnerabilities in the code.