As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.
The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:
-sS use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
--min-rate 5000 nmap will try to keep the sending rate at or above 5000 packets per second.
-p- scanning the entire port range, from 1 to 65535.
-T5insane mode, it is the fastest mode of the nmap time template.
-Pn assume the host is online.
-n scan without reverse DNS resolution.
-oNsave the scan result into a file, in this case the allports file.
# Nmap 7.92 scan initiated Wed Jun 22 11:01:43 2022 as: nmap -sS -p- --min-rate 5000 -Pn -n -oN allPorts 10.10.10.222
Nmap scan report for 10.10.10.222
Host is up (0.056s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8065/tcp open unknown
# Nmap done at Wed Jun 22 11:01:57 2022 -- 1 IP address (1 host up) scanned in 13.62 seconds
Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:
-sC performs the scan using the default set of scripts.
-sV enables version detection.
-oNsave the scan result into file, in this case the targeted file.
# Nmap 7.92 scan initiated Wed Jun 22 11:02:34 2022 as: nmap -sCV -p22,80,8065 -oN targeted 10.10.10.222
Nmap scan report for 10.10.10.222
Host is up (0.037s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh 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)
| 256 5a:0c:c0:3b:9b:76:55:2e:6e:c4:f4:b9:5d:76:17:09 (ECDSA)
|_ 256 b7:9d:f7:48:9d:a2:f2:76:30:fd:42:d3:35:3a:80:8c (ED25519)
80/tcp open http nginx 1.14.2
|_http-title: Welcome
|_http-server-header: nginx/1.14.2
8065/tcp open unknown
| fingerprint-strings:
| GenericLines, Help, RTSPRequest, SSLSessionReq, TerminalServerCookie:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Accept-Ranges: bytes
| Cache-Control: no-cache, max-age=31556926, public
| Content-Length: 3108
| Content-Security-Policy: frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com
| Content-Type: text/html; charset=utf-8
| Last-Modified: Wed, 22 Jun 2022 08:51:53 GMT
| X-Frame-Options: SAMEORIGIN
| X-Request-Id: i1sxxey8mbdk3pmyzc5z7shk6c
| X-Version-Id: 5.30.0.5.30.1.57fb31b889bf81d99d8af8176d4bbaaa.false
| Date: Wed, 22 Jun 2022 09:02:51 GMT
| <!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"><meta name="robots" content="noindex, nofollow"><meta name="referrer" content="no-referrer"><title>Mattermost</title><meta name="mobile-web-app-capable" content="yes"><meta name="application-name" content="Mattermost"><meta name="format-detection" content="telephone=no"><link re
| HTTPOptions:
| HTTP/1.0 405 Method Not Allowed
| Date: Wed, 22 Jun 2022 09:02:51 GMT
|_ Content-Length: 0
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8065-TCP:V=7.92%I=7%D=6/22%Time=62B2DAB8%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20t
SF:ext/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x
SF:20Request")%r(GetRequest,DF3,"HTTP/1\.0\x20200\x20OK\r\nAccept-Ranges:\
SF:x20bytes\r\nCache-Control:\x20no-cache,\x20max-age=31556926,\x20public\
SF:r\nContent-Length:\x203108\r\nContent-Security-Policy:\x20frame-ancesto
SF:rs\x20'self';\x20script-src\x20'self'\x20cdn\.rudderlabs\.com\r\nConten
SF:t-Type:\x20text/html;\x20charset=utf-8\r\nLast-Modified:\x20Wed,\x2022\
SF:x20Jun\x202022\x2008:51:53\x20GMT\r\nX-Frame-Options:\x20SAMEORIGIN\r\n
SF:X-Request-Id:\x20i1sxxey8mbdk3pmyzc5z7shk6c\r\nX-Version-Id:\x205\.30\.
SF:0\.5\.30\.1\.57fb31b889bf81d99d8af8176d4bbaaa\.false\r\nDate:\x20Wed,\x
SF:2022\x20Jun\x202022\x2009:02:51\x20GMT\r\n\r\n<!doctype\x20html><html\x
SF:20lang=\"en\"><head><meta\x20charset=\"utf-8\"><meta\x20name=\"viewport
SF:\"\x20content=\"width=device-width,initial-scale=1,maximum-scale=1,user
SF:-scalable=0\"><meta\x20name=\"robots\"\x20content=\"noindex,\x20nofollo
SF:w\"><meta\x20name=\"referrer\"\x20content=\"no-referrer\"><title>Matter
SF:most</title><meta\x20name=\"mobile-web-app-capable\"\x20content=\"yes\"
SF:><meta\x20name=\"application-name\"\x20content=\"Mattermost\"><meta\x20
SF:name=\"format-detection\"\x20content=\"telephone=no\"><link\x20re")%r(H
SF:TTPOptions,5B,"HTTP/1\.0\x20405\x20Method\x20Not\x20Allowed\r\nDate:\x2
SF:0Wed,\x2022\x20Jun\x202022\x2009:02:51\x20GMT\r\nContent-Length:\x200\r
SF:\n\r\n")%r(RTSPRequest,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConten
SF:t-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n
SF:400\x20Bad\x20Request")%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r
SF:\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close
SF:\r\n\r\n400\x20Bad\x20Request")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x2
SF:0Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nCon
SF:nection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(TerminalServerCookie
SF:,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;
SF:\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request"
SF:);
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 at Wed Jun 22 11:04:15 2022 -- 1 IP address (1 host up) scanned in 100.60 seconds
Let's take a look at the website on port 80.
If we press on the CONTACT US button, a message pop up will appear saying that we need an @delivery.htb email address to have access to the MatterMost server.
If we click on the MatterMost server button, we'll be redirected to the delivery.htb domain on port 8065, and if click on the HelpDesk button, we'll be redirected to the helpdesk.delivery.htb domain. Let's add these domains to the /etc/hosts file, so we can access those websites.
Now, we can access the helpdesk.delivery.htb site.
And to the MatterMost web server.
Exploitation
Let's try to create a new account by clicking on the Create one now button.
But we get a message saying that we must verify our email. But we can't because that email doesn't exist, and if we enter an existent email, we won't get any verification email because the HTB machines doesn't have internet connection. So, we can't create an account for now. If we take a look at the other website, we'll see that it is a Support Ticket System site. Let's open a new ticket with some random information.
And the support ticket request is created.
We could check the ticket status by indicating the email and the ticket ID.
Now, we can see the ticket information.
Notice that when we created the ticket, we got a message saying the following.
If you want to add more information to your ticket, just email 6483323@delivery.htb.
This means that if the 6483323@delivery.htb email address receive any information, that information will be shown on the ticket thread. We create a new user in the MatterMost web server by taking advantage of this system. The idea is to create a user on the MatterMost web server with the 6483323@delivery.htb email address, so the confirmation email will appear on the ticket thread, and we'll be able to verify the account. Let's do it.
Now, we should get the verification email in the ticket thread.
Now, all we have to do is access the following URL to get the account verified.
If we read the chat messages, we'll see that the root user is giving the maildeliverer:Youve_G0t_Mail! credentials. And he is saying that they are using passwords that are a variant of PleaseSubscribe!.
If we try to log in via SSH with those credentials, we'll be able to get a shell as the maildeliverer user and we'll be able to grab the user flag.
Linux Delivery 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Jan 5 06:09:50 2021 from 10.10.14.5
maildeliverer@Delivery:~$ whoami
maildeliverer
maildeliverer@Delivery:~$ cat user.txt
307dc48ceb606480b91244ae6fbd85ca
Privilege Escalation
At this point, I started enumerating the machine, and I found the /opt/mattermost/config/config.json config file with some MySQL credentials.
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 68
Server version: 10.3.27-MariaDB-0+deb10u1 Debian 10
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
Now, let's list the databases.
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mattermost |
+--------------------+
2 rows in set (0.001 sec)
Then, access the mattermost database, and list all the tables.
use mattermost;
show tables;
MariaDB [(none)]> use mattermost;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [mattermost]> show tables;
+------------------------+
| Tables_in_mattermost |
+------------------------+
| Audits |
| Bots |
| ChannelMemberHistory |
| ChannelMembers |
| Channels |
| ClusterDiscovery |
| CommandWebhooks |
| Commands |
| Compliances |
| Emoji |
| FileInfo |
| GroupChannels |
| GroupMembers |
| GroupTeams |
| IncomingWebhooks |
| Jobs |
| Licenses |
| LinkMetadata |
| OAuthAccessData |
| OAuthApps |
| OAuthAuthData |
| OutgoingWebhooks |
| PluginKeyValueStore |
| Posts |
| Preferences |
| ProductNoticeViewState |
| PublicChannels |
| Reactions |
| Roles |
| Schemes |
| Sessions |
| SidebarCategories |
| SidebarChannels |
| Status |
| Systems |
| TeamMembers |
| Teams |
| TermsOfService |
| ThreadMemberships |
| Threads |
| Tokens |
| UploadSessions |
| UserAccessTokens |
| UserGroups |
| UserTermsOfService |
| Users |
+------------------------+
46 rows in set (0.001 sec)
We get a bunch of hashes. If you remember, the root user said in the chat that the password was a variant of the PleaseSubscribe! password. Let's create a custom wordlist with hashcat with variants of that password. First, let's put that password in the pwd file.
echo 'PleaseSubscribe!' > pwd
And now, let's create the custom wordlist with hashcat using the best64 rule, and put the output in the pwds file.
--stdout don't crack a hash, instead print candidates only.
-r multiple rules applied to each word from wordlists.
Now, let's put the root hash in the hash file, and try to crack it with john, using the pwds wordlist.
john --wordlist=pwds hash
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
PleaseSubscribe!21 (?)
1g 0:00:00:00 DONE (2022-06-23 16:49) 1.190g/s 42.85p/s 42.85c/s 42.85C/s PleaseSubscribe!12..PleaseSubscrio
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
And we get the PleaseSubscribe!21 password. Now, all we have to do is become the root user, and reap the harvest and take the root flag.