# Attacking Web Applications with Ffuf

## Overview

En este módulo aprendí cómo enumerar archivos y directorios de una aplicación web, técnicas para descubrir vhosts y subdominios, fuzzing para encontrar parámetros ocultos por GET y POST, así como también para descubrir valores válidos a partir de los parámetros encontrados.

Si bien existen unas cuantas herramientas para aplicar fuzzing, en este módulo se explica el uso de Ffuf ('Fuzz Faster U Fool'), que está programada en Go.

***

## Directory Fuzzing

Lo primero que tenemos que hacer es desplegar el target, ya que vamos a estar utilizando el mismo en todas las secciones del módulo, a excepción de la última.

Debemos encontrar otro directorio, aparte de /blog. Para eso, le indicamos a ffuf un diccionario de rutas y la URL bajo la cual queremos aplicar fuzzing.&#x20;

Además, en mi caso le voy a añadir la flag `-ic` porque la herramienta considera los comentarios del copyright del diccionario como parte del mismo, por lo que el output es medio confuso. Con esa flag, los comentarios del comienzo del diccionario no se consideran.

<pre class="language-bash"><code class="lang-bash"><strong>$ ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://94.237.53.58:33138/FUZZ -ic
</strong></code></pre>

El otro directorio existente es `forum`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2F01GXhRzxWo11KvbeMfKF%2Fimage1.png?alt=media&#x26;token=b29f5cbb-8865-4b74-9c57-a54a34bffb78" alt=""><figcaption></figcaption></figure>

***

## Page Fuzzing

Acá hay que repetir tal cual el procedimiento que nos enseñan en la sección. Primero fuzzeamos dentro del directorio /blog para encontrar qué extensiones existen usando un nombre de archivo común en casi todas las aplicaciones web: `index.*`

```bash
ffuf -w /opt/useful/SecLists/Discovery/Web-Content/web-extensions.txt:FUZZ -u http://94.237.53.58:33138/blog/indexFUZZ -ic
```

En este caso, hay dos extensiones: `.php` y `.phps`

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FgOJxAFm5pJXFiKO0a0b9%2Fimage2.png?alt=media&#x26;token=f25d8394-4915-4f49-9f36-17e3149a462d" alt=""><figcaption></figcaption></figure>

Ahora probamos a descubrir nombres de archivo con esas extensiones en específico.

<pre class="language-bash"><code class="lang-bash"><strong>$ ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://94.237.53.58:33138/blog/FUZZ.php -ic
</strong></code></pre>

Encontramos un archivo `/home.php`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FnAbW0svCOYP20mQR6PWR%2Fimage3.png?alt=media&#x26;token=119b154a-f9d5-42dd-a27d-397209ba04dc" alt=""><figcaption></figcaption></figure>

Si visitamos la página en el navegador, podremos visualizar la flag: `HTB{bru73_f0r_c0mm0n_*********}`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FNQg7sK1f3TgpxpepM4f2%2Fimage4.png?alt=media&#x26;token=341213c6-8f4e-4330-96af-8ca0accb8278" alt=""><figcaption></figcaption></figure>

***

## Recursive Fuzzing

Este ejercicio consiste en aplicar fuzzing de forma recursiva para descubrir más directorios/archivos.

```bash
$ ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://94.237.53.58:33138/FUZZ -recursion -recursion-depth 1 -e .php -v -ic
```

Después de esperar un ratito, vemos un archivo interesante dentro del directorio /forum.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2Fm2JQ7f8gZV49j4Sv1wlk%2Fimage5.png?alt=media&#x26;token=0574f416-4ab3-4bbd-a748-9b762e807566" alt=""><figcaption></figcaption></figure>

La flag es `HTB{fuzz1n6_***_****}`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2Fqx4j7vS8vnXmTzIMGwtr%2Fimage6.png?alt=media&#x26;token=8fa323a2-fb6e-4a41-9d07-90d21f887560" alt=""><figcaption></figcaption></figure>

***

## DNS Records

En Page Fuzzing, había un mensaje en la página web que indicaba que el panel de admin se había movido a academy.htb. Sin embargo, si intentáramos acceder con ese dominio, no lo lograríamos. Esto ocurre porque el sistema no sabe a qué IP tiene que resolver academy.htb. Para indicárselo, tenemos que añadir una línea al archivo /etc/hosts con el siguiente comando.

```bash
$ sudo sh -c 'echo "94.237.53.58 academy.htb" >> /etc/hosts'
```

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FWLWw7DpUN2cUyjVdkyoM%2Fimage7.png?alt=media&#x26;token=ce692739-1b6a-4856-bfeb-ef6df2b59457" alt=""><figcaption></figcaption></figure>

Ahora sí podemos acceder, aunque no nos resulta de mucha utilidad ya que es exactamente la misma página accesible desde la IP. No se está aplicando Virtual Hosting.

Con el dominio:

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2Fv5aecU9C8dcZp5e1WoFJ%2Fimage8.png?alt=media&#x26;token=b8a84acb-c9fc-444a-88fa-f2295e8ed396" alt=""><figcaption></figcaption></figure>

Con la IP:

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2F0C52EmnXSbZdrYS1MJ46%2Fimage9.png?alt=media&#x26;token=dfe3b531-76da-4de8-b37b-5acbb9c54275" alt=""><figcaption></figcaption></figure>

***

## Sub-domain Fuzzing

El objetivo es encontrar un subdominio de 'inlanefreight.com' para clientes. Lo podemos encontrar de la siguiente forma:

```bash
ffuf -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u https://FUZZ.inlanefreight.com/ -ic
```

El subdominio es `customer.inlanefreight.com`.

***

## Filtering Results

Ahora, a diferencia del fuzzing anterior, lo vamos a lanzar en modo VHost. La diferencia radica en que un VHost puede o no estar en registros DNS públicos, mientras que un subdominio se encuentra sí o sí en estos registros DNS. Si no tenemos esto en cuenta, puede que solo vayamos a descubrir subdominios públicos, pero que nunca lleguemos a aquellos que no son públicos pero que sin embargo existen.

Lanzamos un VHost fuzzing scan sobre 'academy.htb'.

```bash
ffuf -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://academy.htb:33138 -H "Host: FUZZ.academy.htb" -fs 986 -ic
```

Hay dos subdominios; la respuesta correcta es `test.academy.htb`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FGrcyrqdK2mZKAs33LoB5%2Fimage10.png?alt=media&#x26;token=bd805e92-3ad2-4127-8d78-ebd8a8e7dfd1" alt=""><figcaption></figcaption></figure>

Corresponde añadir ambos subdominios al /etc/hosts.

<pre class="language-bash"><code class="lang-bash"><strong>$ sudo sh -c 'echo "94.237.53.58 test.academy.htb" >> /etc/hosts'
</strong></code></pre>

```bash
$ sudo sh -c 'echo "94.237.53.58 admin.academy.htb" >> /etc/hosts'
```

***

## Parameter Fuzzing - GET

Fuzzeamos de forma recursiva sobre el subdominio admin.academy.htb para encontrar rutas y archivos.

```bash
$ ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://admin.academy.htb:33138/FUZZ -recursion -recursion-depth 1 -e .php -v -ic
```

Encontramos un archivo admin.php dentro de un directorio admin.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2F283QGzm9lgqrrd621D9V%2Fimage13.png?alt=media&#x26;token=9353f106-f95f-4c88-9ad7-0f23b7d446fa" alt=""><figcaption></figcaption></figure>

Si visitamos la página, veremos que no contamos con acceso a la flag. Esto puede deberse a que la página está esperando recibir un parámetro por GET (en la propia URL) como validación.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FcbcSQViXXPaXZTwI0xmE%2Fimage11.png?alt=media&#x26;token=eba4ab1c-e544-4583-b6e9-acb7e8c2da52" alt=""><figcaption></figcaption></figure>

Por eso, fuzzeamos por parámetros para encontrar alguno que sea válido. Como todas las respuestas devuelven un tamaño de 798 menos la correcta, con `-fs 798` las ocultamos.

```bash
ffuf -w /opt/useful/SecLists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u http://admin.academy.htb:33138/admin/admin.php?FUZZ=key -fs 798 -ic
```

El parámetro es `user`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2Fix8qWeFr9hcKjZrtXvbK%2Fimage12.png?alt=media&#x26;token=fb7281c9-5bb6-4d1d-a1f1-0f8d51cbfcc3" alt=""><figcaption></figcaption></figure>

Sin embargo, si intentamos tramitar una petición GET con este parámetro y cualquier valor, veremos que este método ya no está siendo utilizado.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FN2jrNl30aaPPh0rFJCBE%2Fimage18.png?alt=media&#x26;token=c2698c6e-7df9-4926-9d4b-51a48cb81885" alt=""><figcaption></figcaption></figure>

***

## Parameter Fuzzing - POST

Ya fuzzeamos por parámetros GET, ahora toca lo mismo para parámetros POST.

```bash
$ ffuf -w /opt/useful/SecLists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u http://admin.academy.htb:33138/admin/admin.php -X POST -d 'FUZZ=key' -H 'Content-Type: application/x-www-form-urlencoded' -fs 798 -ic 
```

Encontramos un parámetro `id`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FYktLJhQEiinQfeeBr0JT%2Fimage14.png?alt=media&#x26;token=dc22e048-9c1a-4275-adb5-91acfb9daf1a" alt=""><figcaption></figcaption></figure>

Si tramitamos una petición por POST con la data del id igualado a cualquier valor, veremos en la respuesta el mensaje 'Invalid id!', por lo que nuestro objetivo próximo será encontrar un valor que sea válido.

```bash
$ curl -X POST http://admin.academy.htb:33138/admin/admin.php -d 'id=1' -H 'Content-Type: application/x-www-form-urlencoded'
```

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FsbeJmMjyqQhbhCB6yeFQ%2Fimage15.png?alt=media&#x26;token=98063da0-9f06-4c9a-a88c-7679f359d6fc" alt=""><figcaption></figcaption></figure>

***

## Value Fuzzing

Creamos un diccionario de ids que van desde el 1 hasta el 1000.

```bash
$ for i in $(seq 1 1000); do echo $i >> ids.txt; done
```

Utilizando el diccionario que acabamos de crear, fuzzeamos el parámetro id para encontrar cuál es el válido.

```bash
$ ffuf -w ids.txt:FUZZ -u http://admin.academy.htb:33138/admin/admin.php -X POST -d 'id=FUZZ' -H 'Content-Type: application/x-www-form-urlencoded' -fs 798,768 -ic 
```

El id que devuelve un tamaño de respuesta distinto de 798 y 768 es `73`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FQ7V95cMeaEQR5VxMiVyd%2Fimage16.png?alt=media&#x26;token=ed1a06cb-7379-4454-9d81-d47d50e5b319" alt=""><figcaption></figcaption></figure>

Lanzamos una petición por POST pasando el parámetro id igualado a 73.

<pre class="language-bash"><code class="lang-bash"><strong>$ curl -X POST http://admin.academy.htb:33138/admin/admin.php -d 'id=73' -H 'Content-Type: application/x-www-form-urlencoded'
</strong></code></pre>

Y finalmente obtenemos la flag.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FatNUdNdbp4KoeYb5A5co%2Fimage17.png?alt=media&#x26;token=68edf07f-358a-4fa6-9a5e-aa527d59b072" alt=""><figcaption></figcaption></figure>

***

## Skills Assessment - Web Fuzzing

Desplegamos un nuevo target para esta sección integradora.

La primera consigna consiste en lanzar un escaneo sobre 'academy.htb' para descubrir subdominios. Sin embargo, no nos tenemos que olvidar de primero añadir el dominio al /etc/hosts.

```bash
$ sudo sh -c 'echo "83.136.252.214 academy.htb" >> /etc/hosts'
```

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FzZuGla3LoY0Axqf9LK0I%2Fimage19.png?alt=media&#x26;token=954b1096-9e3d-4cb2-9e94-c9906a5ee9a7" alt=""><figcaption></figcaption></figure>

Ahora sí lanzamos el fuzzing:

```bash
$ ffuf -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://83.136.252.214:34951/ -H 'Host: FUZZ.academy.htb' -fs 985 -ic
```

Descubrimos tres subdominios: `archive,test,faculty`.

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FIyywCKZrYiIbE9YlWh91%2Fimage20.png?alt=media&#x26;token=52c367e9-ee44-4bd9-a385-e85a3d6b8f19" alt=""><figcaption></figcaption></figure>

Continuamos con el siguiente ejercicio: descubrir qué extensiones son aceptadas para TODOS los subdominios. Primero, añadimos los subdominios que enumeramos al /etc/hosts.

```bash
$ sudo sh -c 'echo "83.136.252.214 test.academy.htb" >> /etc/hosts'
```

```bash
$ sudo sh -c 'echo "83.136.252.214 archive.academy.htb" >> /etc/hosts'
```

```bash
$ sudo sh -c 'echo "83.136.252.214 faculty.academy.htb" >> /etc/hosts'
```

Fuzzing para test.academy.htb:

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FG1MLyqC3GfA8cyqlQhdS%2Fimage21.png?alt=media&#x26;token=a6a6e85e-07fe-4aa5-b61a-539e01a2d1ab" alt=""><figcaption></figcaption></figure>

Fuzzing para archive.academy.htb:

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FsUAq6Inu3CPJ9PrbTpSB%2Fimage22.png?alt=media&#x26;token=37a38455-522a-4959-901a-b750040a0432" alt=""><figcaption></figcaption></figure>

Fuzzing para faculty.academy.htb:

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FuFcUmxFBoxN3pYgtYHG8%2Fimage23.png?alt=media&#x26;token=c7abec9b-5320-477b-8512-8ea3bcec5794" alt=""><figcaption></figcaption></figure>

Las extensiones aceptadas son: `.php,.phps,.php7`

Siguiente task. Una de las páginas que vamos a identificar debería decir: 'You don't have access!'

Hay que averiguar cuál es la URL completa.

Para poder descubrirla, la idea es aplicar un fuzzing recursivo.

```bash
$ ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://faculty.academy.htb:34951/FUZZ -recursion -recursion-depth 1 -e .php -v -t 80 -ic
```

Con el parámetro `-t` le añadí hilos para lanzar múltiples tareas en paralelo y agilizar el proceso de fuerza bruta. De entre todos los resultados, este es el que nos interesa:

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FH852qWCXQUCEMjKwqR4f%2Fimage25.png?alt=media&#x26;token=15cb5d3a-2a01-4554-b4c8-6f3cc827a536" alt=""><figcaption></figcaption></figure>

El formato de la respuesta es: `http://faculty.academy.htb:PORT/courses/linux-security.php7`

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FvGe5RbMFPxflmsfdmeRH%2Fimage24.png?alt=media&#x26;token=fb617417-f9e2-4abd-bfc1-ed1bf9209ba0" alt=""><figcaption></figcaption></figure>

En esta misma página deberíamos poder encontrar múltiples parámetros.

Con este comando buscamos parámetros por POST:

```bash
$ ffuf -w /opt/useful/SecLists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u http://faculty.academy.htb:34951/courses/linux-security.php7 -X POST -d 'FUZZ=key' -H 'Content-Type: application/x-www-form-urlencoded' -fs 774 -ic
```

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FnD9fSTIGRwOJ7SCm7i9b%2Fimage26.png?alt=media&#x26;token=a15b3c3d-efd0-4b61-8b0d-a3380285400f" alt=""><figcaption></figcaption></figure>

Encontramos dos válidos: `user,username`.

Por último, fuzzeamos los parámetros con un diccionario que contemple nombres de usuario para encontrar un valor que retorne una flag.

Probamos con el parámetro `user`, pero no vamos a descubrir nada.

```bash
$ ffuf -w /opt/useful/SecLists/Usernames/xato-net-10-million-usernames.txt:FUZZ -u http://faculty.academy.htb:34951/courses/linux-security.php7 -X POST -d 'user=FUZZ' -H 'Content-Type: application/x-www-form-urlencoded' -fs 780 -t 100 -ic
```

Así que probamos con `username`:

```bash
ffuf -w /opt/useful/SecLists/Usernames/xato-net-10-million-usernames.txt:FUZZ -u http://faculty.academy.htb:34951/courses/linux-security.php7 -X POST -d 'username=FUZZ' -H 'Content-Type: application/x-www-form-urlencoded' -fs 781 -t 100 -ic
```

¡Encontramos un nombre de usuario válido para el parámetro!

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2FNB0N1XsdeyOYwPERTRq5%2Fimage27.png?alt=media&#x26;token=969d0667-ee7f-4a01-89ab-8486e658902d" alt=""><figcaption></figcaption></figure>

Lanzamos una petición por POST tramitando como data el parámetro `username` con el valor `harry` y vemos la flag: `HTB{w3b_fuzz1n6_******}`.

```bash
curl -s -X POST http://faculty.academy.htb:34951/courses/linux-security.php7 -d 'username=harry'
```

<figure><img src="https://2256246714-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuERcU4lwQo3nz1NqRbDl%2Fuploads%2F6bTZSg5ETduRZr8mOmS1%2Fimage28.png?alt=media&#x26;token=a8ca6b6d-f3c2-4eec-92ff-7a1d6d712b6f" alt=""><figcaption></figcaption></figure>
