Esta pagina se ve mejor con JavaScript habilitado

HTTP Fuzzing mediante FFuF

 ·  🎃 kr0m

Los fuzzers son herramientas bien conocidas por los pentesters, estos nos permiten inyectar entradas inesperadas a una aplicación para ver como responde, en este caso vamos a utilizar FFuF un fuzzer web que además de poder ver la manera en la que responde la aplicación también nos servirá para descubrir paths y API endpoints.

Instalamos el fuzzer en cuestión:

pkg install ffuf

Cuando fuzeemos haremos sustituciones de partes de las peticiones por otras que nosotros elijamos, una buena lista de palabras a comprobar puede ser la siguiente:

FFuF puede ser vinculado a un proxy que tengamos en marcha, de este modo solo las peticiones que han retornado un código HTTP permitido, por defecto: 200,204,301,302,307,401,403,405,500, serán enviadas a este proxy:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/FUZZ -o output.txt -replay-proxy http://192.168.69.204:8081


        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : https://XXXXXXXXXX.com/FUZZ
 :: Wordlist         : FUZZ: actions.txt
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

admin                   [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 190ms]
:: Progress: [222/222] :: Job [1/1] :: 120 req/sec :: Duration: [0:00:02] :: Errors: 0 ::

Podemos ver como a Burp solo le ha llegado la petición que ha retornado un 302, no las 222:

Si la aplicación requiere el uso de cookies, podemos forjarlas del siguiente modo:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/FUZZ -o output.txt -replay-proxy http://192.168.69.204:8081 -b "Cookie: _ga=GA1.2.135180862.1669714648; _gid=GA1.2.334284534.1669893254; PHPSESSID=cmh79qfsgolamu70lhcvkb4dmi; acceptCookie=1; _gat_gtag_UA_11506612_2=1"

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : https://XXXXXXXXXX.com/FUZZ
 :: Wordlist         : FUZZ: actions.txt
 :: Header           : Cookie: Cookie: _ga=GA1.2.135180862.1669714648; _gid=GA1.2.334284534.1669893254; PHPSESSID=cmh79qfsgolamu70lhcvkb4dmi; acceptCookie=1; _gat_gtag_UA_11506612_2=1
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

admin                   [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 921ms]
:: Progress: [222/222] :: Job [1/1] :: 31 req/sec :: Duration: [0:00:07] :: Errors: 0 ::

Podemos ver como la petición lleva la cookie indicada:

Mediante FFuF también podemos fuzzear cabeceras HTTP:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/admin -o output.txt -replay-proxy http://192.168.69.204:8081 -H "user-agent:FUZZ"

Podemos ver como las peticiones llevan el user-agent fuzzeado:

Si tenemos algún tipo de restricción de tráfico por parte del servidor web, balanceador de tráfico, WAF o algún otro mecanismo, podemos limitar las peticiones por segundo mediante el parámetro -r:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/FUZZ -o output.txt -replay-proxy http://192.168.69.204:8081 -rate 2

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : https://XXXXXXXXXX.com/FUZZ
 :: Wordlist         : FUZZ: actions.txt
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

admin                   [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 192ms]
:: Progress: [222/222] :: Job [1/1] :: 2 req/sec :: Duration: [0:00:52] :: Errors: 0 ::

También es posible fuzzear dos parámetros de forma simultánea:

ffuf -w actions.txt:FUZZ -w actions.txt:SECOND -u https://XXXXXXXXXX.com/FUZZ/SECOND -o output.txt -replay-proxy http://192.168.69.204:8081

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : https://XXXXXXXXXX.com/FUZZ/SECOND
 :: Wordlist         : FUZZ: actions.txt
 :: Wordlist         : SECOND: actions.txt
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________


:: Progress: [49284/49284] :: Job [1/1] :: 119 req/sec :: Duration: [0:06:58] :: Errors: 0 ::

Los resultados devueltos por FFuF pueden ser filtrados de dos modos distintos.
Matchers: Muestra peticiones/respuestas cuyo patrón machee.

MATCHER OPTIONS:
  -mc                 Match HTTP status codes, or "all" for everything. (default: 200,204,301,302,307,401,403,405,500)
  -ml                 Match amount of lines in response
  -mmode              Matcher set operator. Either of: and, or (default: or)
  -mr                 Match regexp
  -ms                 Match HTTP response size
  -mt                 Match how many milliseconds to the first response byte, either greater or less than. EG: >100 or <100
  -mw                 Match amount of words in response

Filters: Elimina peticiones/respuestas cuyo patrón machee.

FILTER OPTIONS:
  -fc                 Filter HTTP status codes from response. Comma separated list of codes and ranges
  -fl                 Filter by amount of lines in response. Comma separated list of line counts and ranges
  -fmode              Filter set operator. Either of: and, or (default: or)
  -fr                 Filter regexp
  -fs                 Filter HTTP response size. Comma separated list of sizes and ranges
  -ft                 Filter by number of milliseconds to the first response byte, either greater or less than. EG: >100 or <100
  -fw                 Filter by amount of words in response. Comma separated list of word counts and ranges

En este ejemplo solo vamos a machear respuestas 302:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/FUZZ -o output.txt -replay-proxy http://192.168.69.204:8081 -fc 302

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : https://XXXXXXXXXX.com/FUZZ
 :: Wordlist         : FUZZ: actions.txt
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response status: 302
________________________________________________

:: Progress: [222/222] :: Job [1/1] :: 119 req/sec :: Duration: [0:00:02] :: Errors: 0 ::

A veces la página responde con un 200 pero un mensaje de error como podría ser:

{ 'not found': true }

En tal caso podemos desechar estas respuestas con el siguiente filtro:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/FUZZ -o output.txt -replay-proxy http://192.168.69.204:8081 -fr "not found"

Por supuestos FFuF también nos permite enviar peticiones POST, si interceptamos un login podemos ver los siguientes campos posteados:

Nos disponemos a fuzzear el campo validar:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/cliente -o output.txt -replay-proxy http://192.168.69.204:8081 -X POST -d "nick=kr0m%40alfaexploit.com&pwd=123PASSWORD123&recordarme=1&validar=FUZZ"


        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : https://XXXXXXXXXX.com/cliente
 :: Wordlist         : FUZZ: actions.txt
 :: Data             : nick=kr0m%40alfaexploit.com&pwd=123PASSWORD123&recordarme=1&validar=FUZZ
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

:: Progress: [222/222] :: Job [1/1] :: 8 req/sec :: Duration: [0:00:24] :: Errors: 0 ::

En Burp podemos ver las peticiones enviadas:

Un aspecto muy interesante de FFuF es que no nos limita a fuzzear los valores de los parámetros existentes si no que podemos fuzzear los propios parámetros:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/cliente -o output.txt -replay-proxy http://192.168.69.204:8081 -X POST -d "nick=kr0m%40alfaexploit.com&pwd=123PASSWORD123&recordarme=1&validar=&FUZZ=valor_inventado"

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : https://XXXXXXXXXX.com/cliente
 :: Wordlist         : FUZZ: actions.txt
 :: Data             : nick=kr0m%40alfaexploit.com&pwd=123PASSWORD123&recordarme=1&validar=&FUZZ=valor_inventado
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

:: Progress: [222/222] :: Job [1/1] :: 5 req/sec :: Duration: [0:00:38] :: Errors: 0 ::

En Burp podemos ver las peticiones enviadas:

También podemos postear parámetros Json:

ffuf -w actions.txt -u https://XXXXXXXXXX.com/cliente -o output.txt -replay-proxy http://192.168.69.204:8081 -X POST -H "Content-Type: application/json" -d "{'FUZZ':'kr0m%40alfaexploit.com'}"

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0-dev
________________________________________________

 :: Method           : POST
 :: URL              : https://XXXXXXXXXX.com/cliente
 :: Wordlist         : FUZZ: actions.txt
 :: Header           : Content-Type: application/json
 :: Data             : {'FUZZ':'kr0m%40alfaexploit.com'}
 :: Output file      : output.txt
 :: File format      : json
 :: Follow redirects : false
 :: Calibration      : false
 :: ReplayProxy      : http://192.168.69.204:8081
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

:: Progress: [222/222] :: Job [1/1] :: 5 req/sec :: Duration: [0:00:37] :: Errors: 0 ::

En Burp podemos ver las peticiones enviadas:

Si te ha gustado el artículo puedes invitarme a un RedBull aquí