Still Fuzzing Faster

(U Fool)



HelSec Virtual Meetup 2020 / @joohoi

whoami

Joona Hoikkala

  • @joohoi (everywhere on the interwebs)
  • Backend dev / sysadmin for almost two decades
  • Open source stuff: acme-dns, ffuf, certbot

Wait what?


GET /helsec/ HTTP/1.1
Host: ffuf.io.fi
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
DNT: 1
Pragma: no-cache
Cache-Control: no-cache
		 

GET /helsec/FUZZ HTTP/1.1
Host: ffuf.io.fi
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
DNT: 1
Pragma: no-cache
Cache-Control: no-cache
		 

GET /helsec/ HTTP/1.1
Host: FUZZ.io.fi
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
DNT: 1
Pragma: no-cache
Cache-Control: no-cache
		 

Input content

  • Password lists, user lists
  • Known API paths
  • Common resource paths, parameter names and values
  • Mutations of valid input data

Common targets

  • GET parameters: names, values or both
  • Headers: Host, authentication, cookies, proxy headers...
  • POST data: form data, JSON, files...

What to look for (matching)

  • Response codes
  • Content ( regexes \o/ )
  • Response sizes (bytes, # of words)

Available tools

  • Burp Suite
  • OWASP ZAP
  • dirb
  • dirbuster
  • wfuzz
  • gobuster
  • ...ffuf

Why yet another?

Demo time

Resource discovery

ffuf -w "/path/to/wordlist" -u "https://ffuf.io.fi/FUZZ" -t 100 -c

Password bruteforcing

ffuf -c -X POST -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=joohoi&password=FUZZ" -w passwords.txt \
     -u "https://ffuf.io.fi/login.php" -fr "error"

Multiple wordlists

(and HTTP Basic auth bruteforcing)

ffuf -c -w "users.txt:USER" -w "passwords.txt:PASS" \
    -u "https://USER:PASS@ffuf.io.fi/secure/" -fc 401

Virtualhost discovery

ffuf -c -w SecLists/Discovery/DNS/fierce-hostlist.txt \
     -H "Host: FUZZ.ffuf.io.fi" -t 1000 -u "http://ffuf.io.fi/"

Parameter discovery

ffuf -c -w "~/SecLists/Discovery/Web-Content/burp-parameter-names.txt" \
    -u "https://ffuf.io.fi/content.php?FUZZ=true"

GET parameter fuzzing

seq 1 10000 > numbers.txt && \
ffuf -c -w "numbers.txt" -u "https://ffuf.io.fi/content.php?id=FUZZ"

XSS helper: find filtered characters

# chars.txt with a list of special characters and/or strings
ffuf -w chars.txt -u https://ffuf.io.fi/reflection.php?data=abcdFUZZefg \
    -c -v -fr "abcdFUZZefg"

Template injection

# ti.txt with different template injection payloads with a common outcome
ffuf -w ti.txt -u https://ffuf.io.fi/reflection.php?ti=FUZZ -mr 'abc42abc' -v -c

What the fuzz?

Enter the mutator!

Using Radamsa to mutate valid inputs.

ffuf -c --input-cmd 'radamsa --seed $FFUF_NUM valid1.txt valid2.txt' \
     -X POST -H "Content-Type: application/json" -t 100 \
     -u https://auth.acme-dns.io/register -d 'FUZZ' -mc all

Pre-generating mutations

radamsa -n 100 -o %n.txt valid1.txt valid2.txt 

# Now we should have 100 files with different payloads

ffuf -c --input-cmd 'cat $FFUF_NUM.txt' \
     -X POST -H "Content-Type: application/json" -t 100 \
     -u https://auth.acme-dns.io/register -d 'FUZZ' -mc all

Parse config from raw HTTP request

Save the raw request from browser, Burp etc.

▶ cat req.txt
GET / HTTP/1.1
Host: ffuf.io.fi
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
DNT: 1
Pragma: no-cache
Cache-Control: no-cache

And ffuf we go

ffuf -request "req.txt"

Advanced output: Burp

ffuf -w "/path/to/wordlist" -u "https://ffuf.io.fi/FUZZ" -t 100 -c \
    --replay-proxy "http://127.0.0.1:8080"

Advanced output: HTML report

ffuf -w "/path/to/wordlist" -u "https://ffuf.io.fi/FUZZ" -t 100 -c \
    -of html -o output.html

Advanced output: JSON

ffuf -w "/path/to/wordlist" -u "https://ffuf.io.fi/FUZZ" -t 100 -c \
    -of json -o output.json

Advanced output: raw

ffuf -w "/path/to/wordlist" -u "https://ffuf.io.fi/FUZZ" -c \
    -od raw_output

Thanks!

Resources from this talk

If you have questions or comments, you can contact me over Twitter, GitHub or CitySec Mattermost: @joohoi