Fuzzing Art with Wfuzz - Basic

Fuzzing Art with Wfuzz - Basic

Fuzzing refers to a testing technique that sends various types of user input to a certain interface to study how it would react. If we were fuzzing for SQL injection vulnerabilities, we would be sending random special characters and seeing how the server would react.

If we were fuzzing for a buffer overflow, we would be sending long strings and incrementing their length to see if and when the binary would break.

There are many tools and methods to utilize for directory and parameter fuzzing/brute-forcing, however I will focus on wfuzz, my personal favorite.

What will we discuss next?

  • Fuzzing directories
  • Fuzzing files and extensions
  • Fuzzing parameter values
  • and much more.

Wfuzz - The Web Fuzzer

From gitHub: github.com/xmendez/wfuzz

Wfuzz has been created to facilitate the task in web applications assessments and it is based on a simple concept: it replaces any reference to the FUZZ keyword by the value of a given payload.

A payload in Wfuzz is a source of data.

This simple concept allows any input to be injected in any field of an HTTP request, allowing to perform complex web security attacks in different web application components, such as: parameters, authentication, forms, directories/files, headers, etc.

Wfuzz is a tool designed for bruteforcing Web Applications, it can be used for finding resources not linked (directories, servlets, scripts, etc), bruteforce GET and POST parameters for checking different kind of injections (SQL, XSS, LDAP,etc), bruteforce Forms parameters (User/Password), Fuzzing,etc.

Installation:

Install using pip:

pip install wfuzz

Install on docker:

docker pull ghcr.io/xmendez/wfuzz

wfuzz Installation

Wfuzz can be used to search for hidden content, such as files and directories, within a web server, allowing you to find additional attack vectors.

Of course, success in finding hidden files or directories depends greatly on what wordlist we use!

As recommended on the Wfuzz site, the most widely used open source wordlists for this task are:

However, due to the limited number of platforms, default installations, known resources such as log files, administrative directories, a considerable number of resources are located in predictable places. Therefore, brute forcing these contents becomes a more feasible task.

But let's go on the attack!

the basic syntax is:

wfuzz -w <wordlist> <url>/FUZZ

or to find common files

wfuzz -w <wordlist> <url>/FUZZ.php

we can also insert two FUZZ parameters for example:

wfuzz -c -z file,<wordlist> -z file,<wordlist> <url>/FUZZ/FUZ2Z.php

in order not to exclude the answers that don't interest us we have to specify what we are interested in.
For example if in our request we want that appear only the results that answer to http 200 and 301 we will write:

wfuzz -w <wordlist> --sc 200,301 <url>/FUZZ.php

wfuzz -w <wordlist> --sc 200,301 <url>/FUZZ.php

we have introduced the --sc filter, so here is an excerpt from the wfuzz help menu regarding this:

    --hc/hl/hw/hh N[,N]+      : Hide responses with the specified code/lines/words/chars (Use BBB for taking values from baseline)
    --sc/sl/sw/sh N[,N]+      : Show responses with the specified code/lines/words/chars (Use BBB for taking values from baseline)
    --ss/hs regex             : Show/hide responses with the specified regex within the content
    --filter <filter>         : Show/hide responses using the specified filter expression (Use BBB for taking values from baseline)
    --prefilter <filter>      : Filter items before fuzzing using the specified expression. Repeat for concatenating filters.

POST Request

you can send post and get requests and find a valid response, the basic syntax is:

wfuzz <wordlist or range> -u <url>istproducts.php?cat=FUZZ

For example I want to find all the product IDs in a url, so I would make a query that includes a range:

wfuzz POST Request

As you know in the range 0-50 are included all requests with 200 OK response from the server, of course check them all would be a waste of time.

So, let's find what stays the same in all requests and what changes.

As you can see the only column where there are differences is Chars.

This means most likely that requests with different values will be pages where the content changes.
For example, if the page contains only "404 it doesn't exist!" I'll have a count of 21 ch so answer 200 OK but in the page there is nothing if it results with 17 ch it could contain something else.

The next step is to exclude the pages with the same ch:

wfuzz filter

As you can see below parameter 1 and 2 have more pictures and text than parameter 4

wfuzz filter page

This concept of filters is applicable to any query we make with Wfuzz.

Something more exciting, if I wanted to try to find a password for a user with wfuzz the basic syntax would be:

wfuzz -z file,<wordlist> -d "<request>" --hc 302 <url>

We can also insert 2 wordlists with the method FUZZ and FUZ2Z, this, for example if we don't know any user or password.

Let's go to the action.

I capture the request with the inspector of firefox, in the tab network (I insert random things and capture) in this way:

wfuzz -z file,<wordlist> -d "<request>" --hc 302 <url>

I'm going to use the test user, let's pretend we found it within a post, I'm going to proceed like this:

Will use a word list and 2 equal FUZZ parameters so that the system tries both words within the wordlist for both username and password (this is a real world test, I hope it's not that easy) of course I added the filter -hc 302.

username pass fuzz

Cookies 🍪 Fuzz

To send your own cookies to the server, for example, to associate a request to HTTP sessions, you can use the -b parameter (repeat for various cookies):

wfuzz -w <wordlist> -b cookie=value1 -b cookie2=value2 -u <url>/FUZZ

Cookies can also be fuzzed:

wfuzz -w <wordlist> -b cookie=FUZZ -b cookie2=value2 -u <url>

Fuzzing Custom headers

Very similarly to cookie fuzzing we can send requests to manipulate the headers:

wfuzz -w <wordlist> -H "Header: headervalue" -H "MyHeader2: headervalue2" -u <url>/FUZZ

You can modify existing headers, for example, for specifying a custom user agent, execute the following:

wfuzz -w <wordlist> -H "Header: headervalue" -H "User-Agent: Googlebot" -u <url>/FUZZ

Headers can also be fuzzed:

wfuzz -w <wordlist> -H "Header: FUZZ" -u <url>/FUZZ

Fuzz the Verbs

HTTP verbs fuzzing can be specified using the -X switch or perform the requests using a specific verb you can also use "-X HEAD".

wfuzz -z list,GET-HEAD-POST-TRACE-OPTIONS -X FUZZ -u <url>

Fuzz the Verbs

Proxies

Need the proxy? No problem, just use the -p tag.
In wfuzz you can use proxy simply by entering -p localhost:8080 in the query like this:

wfuzz -w <wordlist> -p <proxy>:<proxy port> <url>/FUZZ

In addition to http protocol is also supported SOCKS4 and SOCKS5, so our request will become:

wfuzz -w <wordlist> -p <proxy>:<proxy port>:SOCKS5 <url>/FUZZ

We can also use several proxies simultaneously, just specify more p tags:

wfuzz -w <wordlist> -p <proxy>:<proxy port> -p <proxy2>:<proxy2 port> <url>/FUZZ

This can be very convenient if you have to use burp for example:

Proxies

Remember that, if like me, you use Wfuzz on docker, you have to create in burp a proxy listener like this:

burp proxy

Authentication

Wfuzz can set an authentication headers by using the -basic/ntlm/digest command line switches.

For example, a protected resource using Basic authentication can be fuzzed using the following command:

wfuzz -z list,nonvalid-httpwatch --basic FUZZ:FUZZ <url>

Recursion

The -R switch can be used to specify a payload recursion's depth.

For example, if you want to search for existing directories and then fuzz within these directories again using the same payload, you can use the following command:

wfuzz -z list,"<directory>" -R1 <url>/FUZZ


As you may have noticed I've used Docker, yes I think it's easier and more convenient not to "dirty" the operating system.

Here is my short tutorial on Wfuzz I hope it is useful, if you think I can add something... write me!

MAN:Wfuzz

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
*                                                      *
* Version up to 1.4c coded by:                         *
* Christian Martorella (cmartorella@edge-security.com) *
* Carlos del ojo (deepbit@gmail.com)                   *
*                                                      *
* Version 1.4d to 3.1.0 coded by:                      *
* Xavier Mendez (xmendez@edge-security.com)            *
********************************************************

Usage:    wfuzz [options] -z payload,params <url>

    FUZZ, ..., FUZnZ  wherever you put these keywords wfuzz will replace them with the values of the specified payload.
    FUZZ{baseline_value} FUZZ will be replaced by baseline_value. It will be the first request performed and could be used as a base for filtering.


Options:
    -h/--help                 : This help
    --help                    : Advanced help
    --filter-help             : Filter language specification
    --version                 : Wfuzz version details
    -e <type>                 : List of available encoders/payloads/iterators/printers/scripts
   
    --recipe <filename>       : Reads options from a recipe. Repeat for various recipes.
    --dump-recipe <filename>  : Prints current options as a recipe
    --oF <filename>           : Saves fuzz results to a file. These can be consumed later using the wfuzz payload.
   
    -c                        : Output with colors
    -v                        : Verbose information.
    -f filename,printer       : Store results in the output file using the specified printer (raw printer if omitted).
    -o printer                : Show results using the specified printer.
    --interact                : (beta) If selected,all key presses are captured. This allows you to interact with the program.
    --dry-run                 : Print the results of applying the requests without actually making any HTTP request.
    --prev                    : Print the previous HTTP requests (only when using payloads generating fuzzresults)
    --efield <expr>           : Show the specified language expression together with the current payload. Repeat for various fields.
    --field <expr>            : Do not show the payload but only the specified language expression. Repeat for various fields.
   
    -p addr                   : Use Proxy in format ip:port:type. Repeat option for using various proxies.
                                Where type could be SOCKS4,SOCKS5 or HTTP if omitted.
   
    -t N                      : Specify the number of concurrent connections (10 default)
    -s N                      : Specify time delay between requests (0 default)
    -R depth                  : Recursive path discovery being depth the maximum recursion level.
    -D depth                  : Maximum link depth level.
    -L,--follow               : Follow HTTP redirections
    --ip host:port            : Specify an IP to connect to instead of the URL's host in the format ip:port
    -Z                        : Scan mode (Connection errors will be ignored).
    --req-delay N             : Sets the maximum time in seconds the request is allowed to take (CURLOPT_TIMEOUT). Default 90.
    --conn-delay N            : Sets the maximum time in seconds the connection phase to the server to take (CURLOPT_CONNECTTIMEOUT). Default 90.
   
    -A, --AA, --AAA           : Alias for -v -c and --script=default,verbose,discover respectively
    --no-cache                : Disable plugins cache. Every request will be scanned.
    --script=                 : Equivalent to --script=default
    --script=<plugins>        : Runs script's scan. <plugins> is a comma separated list of plugin-files or plugin-categories
    --script-help=<plugins>   : Show help about scripts.
    --script-args n1=v1,...   : Provide arguments to scripts. ie. --script-args grep.regex="<A href=\"(.*?)\">"
   
    -u url                    : Specify a URL for the request.
    -m iterator               : Specify an iterator for combining payloads (product by default)
    -z payload                : Specify a payload for each FUZZ keyword used in the form of name[,parameter][,encoder].
                                A list of encoders can be used, ie. md5-sha1. Encoders can be chained, ie. md5@sha1.
                                Encoders category can be used. ie. url
                                Use help as a payload to show payload plugin's details (you can filter using --slice)
    --zP <params>             : Arguments for the specified payload (it must be preceded by -z or -w).
    --zD <default>            : Default parameter for the specified payload (it must be preceded by -z or -w).
    --zE <encoder>            : Encoder for the specified payload (it must be preceded by -z or -w).
    --slice <filter>          : Filter payload's elements using the specified expression. It must be preceded by -z.
    -w wordlist               : Specify a wordlist file (alias for -z file,wordlist).
    -V alltype                : All parameters bruteforcing (allvars and allpost). No need for FUZZ keyword.
    -X method                 : Specify an HTTP method for the request, ie. HEAD or FUZZ
   
    -b cookie                 : Specify a cookie for the requests. Repeat option for various cookies.
    -d postdata               : Use post data (ex: "id=FUZZ&catalogue=1")
    -H header                 : Use header (ex:"Cookie:id=1312321&user=FUZZ"). Repeat option for various headers.
    --basic/ntlm/digest auth  : in format "user:pass" or "FUZZ:FUZZ" or "domain\FUZ2Z:FUZZ"
   
    --hc/hl/hw/hh N[,N]+      : Hide responses with the specified code/lines/words/chars (Use BBB for taking values from baseline)
    --sc/sl/sw/sh N[,N]+      : Show responses with the specified code/lines/words/chars (Use BBB for taking values from baseline)
    --ss/hs regex             : Show/hide responses with the specified regex within the content
    --filter <filter>         : Show/hide responses using the specified filter expression (Use BBB for taking values from baseline)
    --prefilter <filter>      : Filter items before fuzzing using the specified expression. Repeat for concatenating filters.