1. Introduction

WfFuzz is a web application bruteforcer that can be considered an alternative to Burp Intruder as they both have some common features. With both Wfuzz and Burp Intruder we can bruteforce different web applications elements, like GET/POST parameters, cookies, forms, directories, files, HTTP headers, etc.

If we know part of the name of the web file, which is part of the web application, and it accepts the input argument id that is used by the application to locate the resource to be downloaded, usually, we would have to write a bash script similar to this one to do that:

#!/bin/bash

for id in $(seq 1 1000); do
  echo "http://www.target.com/index.php?id=$id"
done

Instead of the echo command, which just prints the URI on the screen, we would have to use a tool like wget or curl or something like that to actually download the resource, which can be analyzed later by VOKA. The script above is very simple, but why should we program such bash scripts if we have wfuzz. With wfuzz this is a simple matter of executing the following:

# python wfuzz.py -v -z range,1-1000 http://www.target.com/index.php?id=FUZZ

2. WFuzz

The basic architecture of the Wfuzz bruteforce program is as follows. It contains the elements listed below:

- payloads: the generated list of data to be sent to the web server.

- encoders: used to encode the payload in several ways, which is useful if the value in some parameter needs to be URL encoded, base64 encoded, or if the value should hold unicode data, etc. There are also hash functions like md5 and sha1, which can also be used to generate hash representation of the payload. A useful feature is a multiple encoding of the same payload, which can be great if some data is first base64 encoded and then only the md5 hash is needed or something like that.

- iterators: used to iterate over all payloads. The iteration process can be done in several ways, but Wfuzz supports the three iterators: product, zip and chain. We need to remember that in our request URI we need to include the words FUZZ, FUZ2Z, FUZ3Z, …, FUZNZ, which will be replaced by the selected payloads in each iteration. The payload for each FUZZ element is selected by each -z option we’re passing the wfuzz command. We can also use the -V option to fuzz all variables in a request, in which case we don’t need the FUZZ keyword.

- plugins: used to extend the features of the wfuzz program.w

- printers: used to output the results in certain formats. Supported formats are: magictree, html,

Upon checking out the SVN repository from Google Code, we can execute the wfuzz.py to present a list of options that is available to use with wfuzz bruteforce program. This can be seen in the output below:

# python wfuzz.py

********************************************************
* Wfuzz  2.0 - The Web Bruteforcer                     *
* Blackhat Arsenal Release                             *
********************************************************

Usage: wfuzz.py [options] <url>

Options:
-c                          : Output with colors
-v                          : Verbose information
-o printer                  : Output format by stderr

-p addr                     : use Proxy (ip:port or ip:port-ip:port-ip:port)
-x type                     : use SOCK proxy (SOCKS4,SOCKS5)
-t N                        : Specify the number of threads (20 default)
-s N                        : Specify time delay between requests (0 default)

-e <type>                   : List of available encodings/payloads/iterators/printers
-R depth                    : Recursive path discovery
-I                          : Use HTTP HEAD instead of GET method (No HTML body responses).
--follow                    : Follow redirections

-m iterator                 : Specify iterator (product by default)
-z payload                  : Specify payload (type,parameters,encoding)
-V alltype                  : All parameters bruteforcing (allvars and allpost). No need for FUZZ keyword.

-X                          : Payload within HTTP methods (ex: "FUZZ HTTP/1.0"). No need for FUZZ keyword.
-b cookie                   : Specify a cookie for the requests
-d postdata                 : Use post data (ex: "id=FUZZ&catalogue=1")
-H headers                  : Use headers (ex:"Host:www.mysite.com,Cookie:id=1312321&user=FUZZ")

--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[s] code/lines/words/chars (Use BBB for taking values from baseline)
--hs regex                  : Hide responses with the specified regex within the response

Keyword: FUZZ,FUZ2Z  wherever you put these words wfuzz will replace them by the payload selected.

Example: - wfuzz.py -c -z file,commons.txt --hc 404 -o html http://www.site.com/FUZZ 2> res.html
         - wfuzz.py -c -z file,users.txt -z file,pass.txt --hc 404 http://www.site.com/log.asp?user=FUZZ&pass=FUZ2Z
         - wfuzz.py -c -z range,1-10 --hc=BBB http://www.site.com/FUZZ{something}

           More examples in the README.

There are multiple options we can use with the Wfuzz program. The most important option is the -z flag, which specifies the payload. Other important options are -b that is used to specify a cookie, -d to declare the POST data and -H, which declares the headers to use with each request sent to the target host. If we need to login with the basic/ntlm or digest authentication we can with the use of –basic, –ntlm or –digest arguments.

2.1. Payloads

We already mentioned that payloads are generated data to be sent to the target web site. There are different kinds of payloads, which are listed and explained below.

  • file: read entries from a file: an example is file, wordlist/general/commons.txt, which specifies all the entries that are contained in the chosen file.
  • stdin: read entries from standard input
  • list: generate entries from a list of objects: an example is list,a-b-c, which specifies the three entries, the letters ‘a’, ‘b’ and ‘c’.
  • hexrand: generate hexadecimal random objects
  • range: generate a range of numbers: an example is range,0-2, which specifies the three entries, the numbers 0,1,2.
  • names: generates all possible combinations used in account naming patterns.
  • hexrange: generate hexadecimal random objects
  • permutation: performs a permutation of the given parameter

All available payloads can be printed with “python wfuzz.py -e payloads”:

# python wfuzz.py  -e payloads
Available payloads:
- file
- list
- hexrand
- range
- names
- hexrange
- permutation

An example command that chooses to fuzz the parameter ‘d’ in the index.php is shown below:

# python wfuzz.py --hc 403 -c -z range,0-2 <a href="https://www.target.com/index.php?d=FUZZ">https://www.target.com/index.php?d=FUZZ</a>
	

2.2. Encoders

Encoders are used to encode the payloads in several ways. The -z option in Wfuzz specifies the payload and its corresponding encoder in format (type, parameters, encoding). All available encoders are listed below:

# python wfuzz.py -e encodings
Available encodings:
 - urlencode
 - double_urlencode
 - first_nibble_hexa
 - html_encoder
 - uri_hexadecimal
 - base64
 - mssql_char
 - uri_double_hexadecimal
 - mysql_char
 - utf8
 - second_nibble_hexa
 - binary_ascii
 - double_nibble_hexa
 - md5
 - none
 - sha1
 - utf8_binary
 - html_encoder_hexa
 - uri_unicode
 - oracle_char
 - random_uppercase
 - html_encoder_decimal

To use an encoder, we need to specify the third option to the -z argument. The following example fuzzes the md5 argument, which accepts the md5 of the user’s password. We’re using the file passwords.txt as a payload, where the md5 of each password (a password is specified in its own line) is computed and fed into the md5 parameter.

# python wfuzz.py -c -z list,passwords.txt,md5 <a href="https://www.target.com/index.php?d=FUZZ">https://www.target.com/index.php?md5=FUZZ</a>
	

2.3. Iterators

Iterators support three methods that can be used to iterate over payloads and are described in detail below:

  • product (default): combines the first and second payload list to construct all possible combinations.
  • zip: takes the first value from the first payload list and combines it with a corresponding value in the second payload list.
  • chain: combines the first and second payload list to make a new bigger payload list.

A good picture representing what each of the iterators does is shown below and was copied from [1]:

To display all the iterators we can use the command below:

# python wfuzz.py -e iterators
Available iterators:
 - product
 - zip
 - chain

2.4. Examples

a. Filter out all the responses with specified status codes, in this case 404:

# python wfuzz -hc 404

b. Use the baseline support to define a default value for each payload and compare the results against it.

# wfuzz.py -c -z range,1-10 --hc=BBB http://www.site.com/FUZZ{something}

c. Use Wfuzz to check a range of hosts specified in hosts.txt if they contain one of the following directories: admin, webmanager, test.

# wfuzz.py -c -z file,hosts.txt -z list,admin-webmanager-test FUZZ/FUZ2Z

d. Use Wfuzz to check whether the C range IP addresses contain either a directory admin or webmanager:

# wfuzz.py -c -z range,1-254 -z list,admin-webmanager http://192.168.1.FUZZ/FUZ2Z

e. Scan the target host through a SOCKS4/SOCKS5 proxy:

# wfuzz.py -x 192.168.1.2:8080 -c -z range,1-254 -z list,admin-webmanager <a href="http://192.168.1.FUZZ/FUZ2Z">http://192.168.1.FUZZ/FUZ2Z</a>
	

f. Crack passwords

# wfuzz –z list,user1-user2 –z list,pass1-pass2 <a href="http://target.com/username=FUZZ&amp;password=FUZ2Z">http://target.com/username=FUZZ&amp;password=FUZ2Z</a>
	

3. WebSlayer

WebSlayer is a graphical user interface for Wfuzz and it is only supported in Windows. When we run the WebSlayer its default user interface can be seen in the picture below:

In the Attack Setup tab there is an URI field, which we must fill with the target URI. Below that are the Headers and POST data input fields. On that tab there’s also an option to set the payload type, which can be: Dictionary, Range or Payload. The Dictionary can be used to load a file containing payloads, while the Range can be used to specify the range for the attack. The most important setting is the Payload, where we can import the payload from the “Payload Generator” tab. An example of defining a range payload in the “Payload Generator” tab can be seen in the picture below:

We’ve set the Range payload starting at number 0 and continuing up until the number 1000. To generate the payload we need to drag and drop the payload in the “Temporal Generators” to the “Payload Creator” at the bottom and pressing on the “Generate PAYLOAD” button. After that the “PAYLOAD” is filled in and we can import that payload in the “Attack Setup” tab. After importing the payload into the attack scenario, we can press on the “Start Attack” button. With the above payload configuration and URI “http://www.target.com/FUZZ“, we should see the requests presented below:

192.168.1.1 - - [03/Oct/2012:23:50:10 +0200] "GET /0 HTTP/1.1" 301 564 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b3) Gecko/2008020514 Firefox/3.0b3"
192.168.1.1 - - [03/Oct/2012:23:50:10 +0200] "GET /1 HTTP/1.1" 301 564 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b3) Gecko/2008020514 Firefox/3.0b3"
192.168.1.1 - - [03/Oct/2012:23:50:10 +0200] "GET /2 HTTP/1.1" 301 564 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b3) Gecko/2008020514 Firefox/3.0b3"
192.168.1.1 - - [03/Oct/2012:23:50:10 +0200] "GET /3 HTTP/1.1" 301 564 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b3) Gecko/2008020514 Firefox/3.0b3"

We’re trying to figure out if a directory, whose name is a number, is present on the web server. This isn’t so useful, but we’re just trying present how WebSlayer works.

The “Attack Results” tab presents the results of the bruteforce iteration. That tab will hold all the requests and their corresponding responses, which we can analyze in detail after the scan is finished.

References:

[1] WFUZZ for Penetration Testers, Christian Martorella & Xavier Mendez, SOURCE Conference, 2011, Barcelona.