10 min read
February 29, 2020

HackTheBox Writeup: Scavenger

Scavenger was a hard rated box which was very frustrating at times due to a crazy amount of rabbitholes. In the end though, I think it was a pretty realistic box that tested enumeration skills as well as methodology. A SQL injection vulnerability in whois uncovered some hidden domains. Enumeration of these domains turned up a php shell that required fuzzing to discover the correct parameter for use. This allowed further enumeration of the box which found ftp credentials, allowing access to a .pcap file recording a security incident. Analysis of the .pcap file showed the beginning stages of the attack and hinted at a rootkit being installed. Finally a bit of reverse engineering on a binary yielded a magic string which allowed code execution as root.

I normally show interesting things found during enumeration but due to the large number of rabbitholes, I will only mention some things in passing.

Enumeration

nmap scan:

I added scavenger.htb and www.supersechosting.htb to my /etc/hosts file. I checked ftp which did not allow anonymous access. A potential vulnerability in Exim but it was local only so I filed that away. Time to check out http:

Ok then, let's enumerate some vhosts:

I added all of these to my /etc/hosts and checked them out - same vhost error on all of them. Next I checked out www.supersechosting.htb which was referenced in the nmap scan:

Let's try a zone transfer:

More things to add to /etc/hosts. I did some more digging around to no avail then switched to whois:

I got stuck here for a while until I took a step back and realized that running whois was user-supplied input. I threw a single quote at it and was somewhat surprised to see a SQL error. In hindsight I shouldn't have been surprised if I had taken a closer look at the nmap scan:

With some experimentation, I was able to get rid of the error with the parenthesis:

Since that worked, time to try adding a tautology:

Sweet, that worked but outputted a ton of data. Let's filter the results with grep to only show the domains:

I added these to /etc/hosts and got the same vhost error as before so I ran dig on these domains:

Even more things to add to /etc/hosts. Finally we see some working webpages:

Rentahacker.htb is running Wordpress 5.0 which has some vulnerabilities that requires credentials so I filed that away. There was also an entry that referenced a bug tracker being pwned:

I ran gobuster on these domains and sec03.rentahacker.htb (which had been pwned) had a suspicious looking file:

shell.php? Not a good sign.

Naturally I tried http://sec03.rentahacker.htb/shell.php?cmd=id which did nothing so I continued enumerating.

Login.php brings you to a MantisBT bugtracker, the one referenced by the hackers:

Clicking on 'MantisBT' brought me to a working login page:

A default administrator password of "root" let me in:

I spent some time exploring the app here but couldn't really get anywhere. There is a place to upload files but I couldn't find where they went.

Initial Foothold/RCE

Eventually I got a nudge to further explore that shell.php file in sec03.rentahacker.htb. With some experimentation:

That worked and now we've got RCE:

I quickly got annoyed at using the browser or Burp Repeater to run commands so I bumbled my way through Python to make a pseudo shell:

It worked well enough to let me start enumerating:

While numerating the box, I found credentials for ib01c01 in wp-config.php:

I was able to dump the Wordpress admin hash which turned out to be another rabbithole but here it is for reference:

These credentials also worked for ftp which didn't come into play for me so I continued enumerating. Eventually I found more credentials hiding in /var/mail:

These credentials worked for ftp and inside we find some interesting files:

Download all the things!

The access logs weren't too helpful but the .pcap had all kinds of interesting things so let's dive in.

PCAP Analysis

I opened up the .pcap file in Wireshark and started looking for login info. The first POST request:

These creds didn't work so I filtered for POST requests with http.request.method == POST. The second request had some creds:

I went to the URL here, plugged in the creds and they worked:

Let's go back to the .pcap for now though. There is one more POST request and if we look in that area, there is suspicious traffic from the victim to the attacker on TCP port 4444:

If we follow the TCP stream of that suspicious traffic, it looks like the attacker had a reverse shell:

The attacker downloads Makefile and root.c to the victim then creates another reverse shell on port 4445 using openssl. Sure enough, it's encrypted:

I examined Makefile and root.c, saving them just in case:

I also took a closer look at the third POST request right before the reverse shell:

Let's see what that suspicious looking ProxyCommand decodes to:

Yup, it's a reverse shell which lead me into...

The Rabbithole From Hell

After seeing the POST request with a reverse shell command, I totally fixated on it. This fixation was further strengthened when I went to the Customer Service section in Prestashop and saw this:

Scroll down a bit and there's a 'Customer Service Options' section where that ProxyCommand is:

I spent many hours cursing while trying to exploit it manually as well as trying to get the metasploit module working. This was easily the most frustrating part of the box for me which was made infinitely worse by it responding super slowly. I'm talking 2 minutes between clicking on a button and having the page load, frequently timing out altogether.

After stubbornly trying for a long time, I caved and got a nudge that this was a rabbithole and to focus on a different service. I tried variations of 'pwnhats' with the 'GetYouAH4t!' password in various places but couldn't get it to work so I kept enumerating with my pseudo shell. Eventually I found the reason why in /etc/apache2/sites-enabled/000-default.conf:

I should have been using 'ib01c01' as a user instead of 'pwnhats'.

Ugggggghhhhh

After removing my palm from my face, I was able to log into the ftp server as ib01c01:

Downloaded some files:

User flag:

access.txt:

I could have used this earlier :/

Privilege Escalation

My first thought was that the Makefile and root.c files from the attacker could be compiled and used to gain root. I got errors trying to compile so took a closer look at them to figure out what the attacker was doing.

Let's look at Makefile first:

obj-m+=root.o
all:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean

Googling for 'makefile obj-m' brought me here which identified it as the makefile for a kernel module.

I'd paste in root.c but it's not cooperating with markdown here. There were two phrases in there that seemed unique enough - 'got r00t' and 'ttyr0' - so I googled and found this article on a rootkit (you can find the full contents of root.c there if you are curious). The gist of the rootkit is a kernel module that creates a ttyR0 device. Send a magic string to that device and you get root privileges. I tried the default string "g0tR0ot" and of course it didn't work so time to dig deeper.

lsmod shows a suspicious module named 'root':

Trying modinfo root fails:

I got stuck here for quite a while. I used my pseudo shell to run find/grep commands looking for root.ko. I crawled all over the file system through ftp and even though I use ls -la by default, I somehow missed a hidden directory right where I started as ib01c01:

See those three dots? I don't know how many times I looked at them without seeing them. Inside there was the root.ko file I had been looking for:

I transferred it over so I could examine it:

I'm still very much a beginner when it comes to reverse engineering so thankfully this was an easy one.

First I ran r2 -A root.ko. The -A analyzes things and is the same thing as running r2 root.ko then aaa at the prompt:

Next, list functions with afl:

From the rootkit article and the root.c file, the part we are interested in is here:

root_write (struct file *f, const char __user *buf, size_t len, loff_t *off)
{
char   *data;
char   magic[] = "g0tR0ot";

It's the 'root_write' function so we'll seek to it with s sym.root_write:

Finally we run pdf which will show the function disassembly:

"g3tPr1v" looks like a proper l33t speak magic phrase and sure enough it works:

Finally the root flag:

Whew, that was a tough one. As frustrating as it got at times with the rabbitholes and false leads, it was a good reminder not to get too fixated on any specific vector and to change gears if you can't get something to work.