Hack The Box - Admirer


Machine info

Operating System: Linux

Difficulty: Easy

Release date: May 12, 2020

IP Address: 10.10.10.187


Misconfiguration
Web
SQL
Python

# Summary

  • Recon
    • Port scanning
    • Web enumeration: contacts info and credentials
    • FTP: web source code backup with known credentials
    • Web enumeration (after source code): Adminer application

  • Machine Access
    • Exploit LFI vulnerability in Adminer
    • Log to the server via SSH

  • Privilege Escalation
    • Enumerate user privileges: user able to run certain scripts as root
    • Exploit Python environment to get reverse shell as root

1. Recon

1.1. Port Scan

As usual, I started scanning the open ports in the box doing a fast scan with nmap:


nmap -p- -T5 --min-rate 5000 --open -v -n -Pn -oA nmap/fast-scan 10.10.10.187
                    

It didn't show a lot of services but keeping in mind that this was an easy machine, I went directly to examine the web application after running the nmap custom scripts and version checks on those ports (which results didn't provide that much info either).

1.2. Web Enumeration

First of all, I checked the HTTP Headers with curl but there were no interesting headers, so I just fired up a proxy (just in case) and opened the web on my browser.

Taking a quick glance at the robots.txt file it shown a juicy directory that was worth investigating:

After doing some brute-force URL enumeration with gobuster using a common wordlist I found a couple of files that worth a look.


gobuster dir -u http://10.10.10.187/admin-dir -w /usr/share/seclists/Discovery/Web-Content/common.txt -s '200,301,302,307,403,500' -e
                    

The credentials.txt file (the one I jumped directly into) contained some credentials for FTP, internal mail and Wordpress:

The contacts.txt file only contained some emails from presumably employees of the company behind the web page as well as their current(?) position:

As both files contained valuable information I decided to grab a quick copy of them with wget before trying to test some of those credentials.

1.3. FTP Enumeration

Testing the gathered FTP credentials from the credentials.txt file (ftpuser : %n?4Wz}R$tTF7) I was able to access the FTP server.

There, I was able to retrieve a database dump and the compressed files of the web application.

Checking really quick the database dump file I found it only had information of the web application images / items.

1.4. Web Enumeration (2)

Browsing through the web application files, it had a directory called utility-scripts which contained some admin utilities that might worth poke a little bit.

However, after taking a look at the index.php, I realized that the file contained a syntax error (the database password contains double quotes, breaking its own string format):

As the web application was currently up and running, that indicated that the found files could be probably a backup of the web application.

Going back to the utility scripts, I decided to enumerate further on that directory. This took quite some time, but after using some big wordlists, I was able to find an interesting route. In the meantime, I grabbed a copy and tooked note of any useful information (i.e. the web application folder path).


wfuzz -c -w /usr/share/wordlists/dirb/big.txt --hc=403,404 -u "http://10.10.10.187/utility-scripts/FUZZ.php" -t 100
                    

This new finding was an Adminer instance, a database management application written in a single PHP file.

My first guess here was to use the database credentials from the downloaded index.php to log into the app but that didn't work.

2. Machine Access

2.1 LFI vulnerability

Doing a little bit of research about the application and its version (shown in its login page), I found out that Adminer ver. 4.6.2 presents a Local File Inclusion vulnerability.

This specific version of Adminer allows an attacker to connect to a database on its own machine from the Adminer application. However, as Adminer is running on the victim machine, it is possible to load the content of a file from the victim system instead from the machine where the application is connected to.

This vulnerability and its exploit are further explained in this article by Foregenix as well on this Medium post by @YShahinzadeh.

2.2 Setup local machine

Checking the port where MariaDB was running, I could see that the port was binded only to localhost. Therefore it would reject any connection from the outside.

In order to fix that, it is only necessary to replace the bind-adress of the server in its configuration file from 127.0.0.1 to 0.0.0.0.


sudo lsof -i:3306
sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf
sudo systemctl restart mysql
sudo lsof -i:3306
                    

After restarting the server and checking again, it was ready to accept connections from other machines:

Then I created a random password and logged into my MariaDB server in order to create a user and database to connect to, assigning the proper permissions:


CREATE DATABASE admirertest;
CREATE USER 'kali'@'%' IDENTIFIED BY "thiethae9xiP6ahthieg";
GRANT ALL PRIVILEGES ON *.* TO 'kali'@'%';
FLUSH PRIVILEGES;
                    

Once the database was created, everything was set to exploit the vulnerability.

2.3 Exploit LFI

Using the newly created database credentials I was able to connect to my test database from the Adminer application.

Knowing that the index.php file from the backup had the database credentials, I decided to load that file by taking advantage of the LFI vulnerability. (This is the moment where the info gathered previously from phpinfo comes in handy).

In order to exploit the vulnerability, first I had to create a database table with a text column that I named test. Then, by sending the following SQL commands, each row of the indicated file was loaded in that table:


LOAD DATA LOCAL INFILE '/var/www/html/index.php'
INTO TABLE test
FIELDS TERMINATED BY "\n"
                    

After submitting the code, each row of the indicated file was loaded as a row of the created table. This shown the current database credentials that the web application was using:

Testing the found username (waldo) and password (&<h5b~yK3F#{PaPB&dA}{H>) on SSH I was able to log into the server as waldo!

3. Privilege Escalation

3.1. Enumerate user privileges

Once I was in the target machine as waldo, while doing the usual enumeration tasks (OS version, permissions, etc.) it seemed waldo could run an admin script passing its own environment to it:

Interesting enough, checking the cronjobs configuration, there was a cronjob configured to delete any Python related files on the home folder.

The Bash admin script (/opt/scripts/admin_tasks.sh) had an option to make a backup of the web directory. In this case, this action was performed invoking an external Python script, instead of performing the backup from the Bash script.

This backup script (/opt/scripts/backup.py) was a very simple Python script as it is shown in the following image. It imports the shutil library in order to use its make_archive function to do the backup of the folder:

Knowing that the current sudo configuration for waldo uses the user environment, it seemed feasible to modify the Python environment with a new one replacing the location where the shutil library was going to get loaded for a malicious one.

3.2. Exploit Python path

In order to perform the exploit, first of all I created a shutil.py file with the function make_archive in it.

I decided to try first with a ping call to my machine as I was getting some trouble getting the PYTHONPATH environment passed to the root process. I found out that the sudo option -E does not work with PATH nor PYTHONPATH and, if required, those environment variables have to be explicitly passed when calling the command (stackoverflow).

After passing the PYTHONPATH variable as indicated in the following picture, I started getting the output from the ping command.


sudo PYTHONPATH=/home/waldo/scripts /opt/scripts/admin_tasks.sh 6
                    

Finally, I modified the make_archive function with a reverse shell. As a side note, it is important to remember that the machine had a cronjob configured to remove any Python files in the home folder, therefore I crafted and modified the malicious Python script on my local machine, copying it to the target and executing the admin script before the next cleanup.

Firing again the admin script with sudo, while having a netcat listener on the attacker machine, I got a reverse shell as root!