Delivery Writeup - HackTheBox
Delivery is a Linux box running two web applications that trust each other by accident. The chain runs: an osTicket helpdesk that hands out a working email address per ticket, a Mattermost registration verified through that address, SSH credentials posted in an internal channel, database credentials in the Mattermost config, and a bcrypt hash that falls in seconds because the same channel leaked the password pattern.
Reconnaissance
Port scan
Open $TARGET_IP:22 Open $TARGET_IP:80 Open $TARGET_IP:8065
Explain command
| -a $TARGET_IP | Address to sweep for open ports across the full range. |
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) 80/tcp open http nginx 1.14.2 |_http-title: Welcome 8065/tcp open http Golang net/http server |_http-title: Mattermost | http-robots.txt: 1 disallowed entry |_/
Explain command
| -sCV | Run the default script set and probe service versions. |
| -p22,80,8065 | Limit the scan to the ports rustscan already found open. |
Two independent web applications: a static nginx site on 80 and a Mattermost team chat on 8065. The site on 80 links to delivery.htb and helpdesk.delivery.htb, so both names go in /etc/hosts.
Enumeration
The helpdesk
view.php [Status: 200] account.php [Status: 200] open.php [Status: 200] manage.php [Status: 200] captcha.php [Status: 200] logout.php [Status: 302] kb [Status: 301] api [Status: 301]
Explain command
| -e .php,.html,.cgi,.txt | Also try these extensions on every wordlist entry. |
| -fs 4933 | Filter out the default response size so only real pages remain. |
That file set is osTicket. A helpdesk accepts input from anonymous users by design, and Mattermost on the same host requires a verified email address before an account can log in. Those two facts combine.
Vulnerability Discovery
A mailbox from a support ticket
Opening a ticket with throwaway details returns a ticket id and, more importantly, an address to reply to.
You may check the status of your ticket, by navigating to the Check Status page using ticket id: 9669049.
If you want to add more information to your ticket, just email 9669049@delivery.htb.
osTicket threads any mail sent to <ticket-id>@delivery.htb into the ticket, and the ticket is readable by whoever holds the id. That is effectively an inbox on the delivery.htb domain, which is exactly what Mattermost wants to verify.
Exploitation
Registering on Mattermost
Registering at http://delivery.htb:8065/ with the ticket address sends the verification mail straight into the ticket thread, where it appears as a new reply.
---- Registration Successful ---- Please activate your email by going to:
http://delivery.htb:8065/do_verify_email?token=w6kjtmttoykocpc1o7b6e8oakp1g37y3kem97wrknp4tdgi4ttkjh71wmup9ceww&email=9669049%40delivery.htb
Following the link activates the account. Neither application validates who is reading the mailbox, and neither knows the other exists.
Credentials in the internal channels
With a verified account the team channels are readable, and one conversation carries two separate leaks.
@developers Please update theme to the OSTicket before we go live.
Credentials to the server are maildeliverer:$MAILDELIVERERS_PASSWORD
Also please create a program to help us stop re-using the same passwords everywhere....
Especially those that are a variant of "$PASSWORD_BASE"
SSH credentials, plus the fact that every password on the box is a mutation of one base string. The second half matters later.
maildeliverer@delivery.htb's password: Linux Delivery 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64 maildeliverer@Delivery:~$ whoami maildeliverer
Foothold as maildeliverer.
Privilege Escalation
Mattermost on disk
linpeas.sh flags /opt, which is empty on a stock Debian install, and here holds the Mattermost installation.
drwxrwxr-x 12 mattermost mattermost 4096 Jul 14 2021 mattermost
"DataSource": "mmuser:$MMUSERS_PASSWORD@tcp(127.0.0.1:3306)/mattermost?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s"
The application's own database credentials sit in cleartext in a file maildeliverer can read. Mattermost keeps its accounts in that database, hashes included.
Reading the users table
mysql> SELECT Username, Password, Roles FROM Users WHERE Username = 'root'; | root | $ROOTS_HASH | system_admin system_user |
Explain command
| -u mmuser | Database user from the config file. |
| -h 127.0.0.1 | Connect over loopback, which is the only interface MariaDB listens on. |
A bcrypt hash with a $2a$ prefix, deliberately slow to attack. A generic wordlist would be hopeless, but the chat already gave the base string, so the only unknown is the mutation applied to it. Hashcat's best64.rule covers exactly that class of change: appended digits, capitalisation, common substitutions.
$ROOTS_HASH:$ROOTS_PASSWORD Recovered........: 1/1 (100.00%) Digests
Explain command
| -m 3200 | Hash mode for bcrypt. |
| --user | Strip the username prefix from the hash file. |
| -r best64.rule | Apply the standard mutation rules to the single base password. |
The recovered password is the Mattermost password for root, and the same reuse habit the channel complained about means it is worth trying against the local account.
Password: root@Delivery:/# whoami root
Root on the box. Both contexts are covered.
Related
References
-
Mattermost configuration settingsDOCS: Mattermost configuration settings, docs.mattermost.com/configure/configuration-settings.html (opens in new tab)
Documents the SqlSettings DataSource string that stores the database credentials.
-
Hashcat rule based attackTOOL: Hashcat rule based attack, hashcat.net/wiki/doku.php?id=rule_based_attack (opens in new tab)
How rule files such as best64.rule mutate a known base password.