Introduction
Many tools have been developed that create an HTTP request
and allow a user to modify their contents. Fuzzing works the same way. A user
can send a similar request multiple times to the server with a certain section of
the request changed. When that certain section is replaced by a variable from a
list or directory, it is called fuzzing.
In this article, we will learn how we can use wfuzz, which
states for “Web Application Fuzzer”, which is an interesting open-source web
fuzzing tool. Since its release, many people have gravitated towards wfuzz,
particularly in the bug bounty scenario. So, let’s dive into this learning
process.
Table of content
·
Introduction to
wfuzz
·
Setup
·
Wfpayload and
Wfencode
·
Docker run wfuzz
·
Payloads
·
Subdomain Fuzzing
·
Directory
Fuzzing
·
Saving fuzzing
output
·
Basic wordlist
filters
·
Double fuzzing
·
Login bruteforce
·
Cookie fuzzing
·
Header fuzzing
·
HTTP OPTIONS
fuzzing
·
Fuzzing through
Proxy
·
Authentication
fuzz
·
Recursive fuzz
·
Printers and
output
·
Encoders
·
Storing and
restoring fuzz from recipes
·
Ignoring
exceptions and errors
·
Filtering
results
·
Sessions in
wfuzz
·
Conclusion
Introduction to Wfuzz
Wfuzz is a python coded
application to fuzz web applications with a plethora of options. It offers
various filters that allow one to replace a simple web request with a required
word by replacing it with the variable “FUZZ.”
Setup
To install wfuzz using pip, we
can:
pip3 install wfuzz
The same could be achieved by
installing from the source using git.
git clone
https://github.com/xmendez/wfuzz.git
The help menu to see all the
working options is as follows:
wfuzz -h
wfuzz --help
You can use a module by using
“-z”
Wfpayload and Wfencode
When you install the tool from
source, compiled executables called wfpayload and wfencode are available. These
are responsible for payload generation and encoding. They can be individually
used. For example, command to generate digits from 0 to 15 is as follows:
./wfpayload -z
range,0-15
As you can see, there is a pycurl
error. It can go away like so:
apt --purge remove
python3-pycurl && apt install libcurl4-openssl-dev libssl-dev
Now, when you run wfencode, which
is a module to encode a supplied input using a hash algorithm, there is no
pycurl error now.
./wfencode -e md5
ignite
Docker run wfuzz
Wfuzz can also be launched using
docker in the following way using the repo ghcr.io. The respective command can
be run by replacing the last variable wfuzz.
docker run -v
$(pwd)/wordlist:/wordlist/ -it ghcr.io/xmendez/wfuzz wfuzz
Payloads
A payload in Wfuzz is a source of
input data. The available payloads can be listed by executing:
wfuzz -e payloads
The detailed view can also be
looked using the slice filter:
wfuzz -z help --slice
"list"
Subdomain Fuzzing
Subdomain discovery is extremely
helpful in pentesting scenarios. Often, attackers launch attacks on subdomains
rather than main domains and it can be fuzzed like so:
Here, -c color codes the output
response codes
-Z specifies a URL to be input in scan mode and ignores any connection error
-w specifies the wordlist use while subdomain bruteforce.
wfuzz -c -Z -w
subdomains.txt http://FUZZ.vulnweb.com
The same can be achieved by
providing the subdomain list inline too. Only, the payload (-z option) should
be supplied in with “list” as an input. The list is supplied in the format
ITEM1-ITEM2-ITEM3 like so:
wfuzz -z
list,CVS-testphp-admin-svn http://testphp.vulnweb.com/FUZZ
wfuzz -z
list,CVS-testphp-admin-svn http://FUZZ.vulnweb.com/
Directory Fuzzing
Directories can be enumerated
using wfuzz just like with gobuster by using a supplied wordlist. This can be
done using a -w flag and input the path of the wordlist:
wfuzz -w
wordlist/general/common.txt http://testphp.vulnweb.com/FUZZ
As you can see in the above
screenshot, all the results including page not found have been dumped which
makes it tedious to go through the results and find pin in a haystack.
Therefore, to sort the results out we can see the show code flag (--sc). Other
such flags are:
·
--hc/sc CODE
#Hide/Show by code in response
·
--hl/sl NUM #ide/Show
by number of lines in response
·
--hw/sw NUM #ide/Show
by number of words in response
·
--hc/sc NUM #ide/Show
by number of chars in response
wfuzz -w
wordlist/general/common.txt --sc 200,301 http://testphp.vulnweb.com/FUZZ
Saving fuzzing output
Wfuzz output can also be saved in
multiple formats using the -f option.
-f option allows a user to input
a file path and specify a printer (which formats the output) after a comma.
wfuzz -w
wordlist/general/common.txt -f /tmp/output,csv --sc 200,301
http://testphp.vulnweb.com/FUZZ
cat /tmp/output
In place of csv, you can specify
any one of the printers
wfuzz -e printers
Basic wordlist filters
There are certain sub-arguments
that can be preceded by -z or -w filter to play around more with. These filters
are:
--zP <params>: Arguments
for the specified payload
--zD <default>: Default
parameter for the specified payload
--zE <encoder>: Encoder for
the specified payload
So, to specify a wordlist with
the payload, we can do it like so:
wfuzz -z file --zD
wordlist/general/common.txt --sc 200,301 http://testphp.vulnweb.com/FUZZ
To hide the HTTP response code
404, the same can be obtained like so:
wfuzz -z file --zD
wordlist/general/common.txt --hc 404 http://testphp.vulnweb.com/FUZZ
Double fuzzing
Just like a parameter in a
payload can be fuzzed using the keyword “FUZZ” multiple fuzzing is also
possible by specifying keywords:
·
FUZ2Z - 2nd parameter
·
FUZ3Z - 3rd parameter
·
FUZ4Z - 4th parameter
And each parameter can be
allotted its own wordlist. The first “-w” stands for first FUZZ. Second “-w”
holds for second FUZ2Z and so on.
wfuzz -w
wordlist/general/common.txt -w wordlist/general/common.txt --hc 404 http://testphp.vulnweb.com/FUZZ/FUZ2Z
Login bruteforce
HTTP responses can be
brute-forced using wfuzz. For example, testphp’s website makes a POST request
to the backend and passes “uname” and “pass” as the arguments to a page
userinfo.php
The same can be implemented using
wfuzz like so:
-d argument specifies the post
data to be sent along the request
wfuzz -z
file,wordlist/others/common_pass.txt -d
"uname=FUZZ&pass=FUZZ"
--hc 302 http://testphp.vulnweb.com/userinfo.php
As you can see, the correct
credentials “test-test” have been found. We used a common file for both
username and password. The same can be done by providing different files for
both usernames and passwords like so:
-c is to color code the output
response which can be skipped.
wfuzz -z
file,users.txt -z file,pass.txt --sc 200 -d
"uname=FUZZ&pass=FUZ2Z" http://testphp.vulnweb.com/userinfo.php
Cookie fuzzing
To send a custom cookie along a
request to different fuzzed directories we can use the “-b” plug. This would
add a cookie to the sent HTTP request.
Scenario useful:
·
Cookie poisoning
·
Session hijacking
·
Privilege Escalation
wfuzz -z
file,wordlist/general/common.txt -b cookie=secureadmin -b cookie2=value2 --hc
404 http://testphp.vulnweb.com/FUZZ
In the above scenario, we have
added 2 static cookies on multiple directories. Now, we can also fuzz the
cookie parameter too like so:
wfuzz -z
file,wordlist/general/common.txt -b cookie=FUZZ http://testphp.vulnweb.com/
Header fuzzing
HTTP header can be added in a
request being sent out by wfuzz. HTTP headers can change the behavior of an
entire web page. Custom headers can be fuzzed or injected in an outgoing
request
Scenarios useful:
·
HTTP Header
Injections
·
SQL Injections
·
Host Header
Injections
wfuzz -z file,wordlist/general/common.txt
-H "X-Forwarded-By: 127.0.0.1" -H "User-Agent: Firefox" http://testphp.vulnweb.com/FUZZ
HTTP OPTIONS fuzzing
There are various HTTP
Request/Options methods available which can be specified by using the “-X”
flag. In the following example, We have inserted the following options in a
text file called options.txt
·
GET
·
HEAD
·
POST
·
PUT
·
DELETE
·
CONNECT
·
OPTIONS
·
TRACE
·
PATCH
wfuzz -c -w options.txt
--sc 200 -X FUZZ “http://testphp.vulnweb.com”
As you could see, three valid options
returned a 200 response code.
The same can be input inline
using the “list” payload like so:
wfuzz -z
list,GET-HEAD-POST-TRACE-OPTIONS -X FUZZ http://testphp.vulnweb.com/
Fuzzing through Proxy
Wfuzz can also route the requests
through a proxy. In the following example, a Burp proxy is active on port 8080
and the request intercepted in the burp intercept as you can see.
wfuzz -z
file,wordlist/general/common.txt -p localhost:8080 http://testphp.vulnweb.com/FUZZ
The same can also be achieved with
SOCKS proxy like so:
wfuzz -z
file,wordlist/general/common.txt -p localhost:9500:SOCKS5
http://testphp.vulnweb.com/FUZZ
Authentication fuzz
Wfuzz can also set authentication
headers and provide means of authentication through HTTP requests.
Flags:
·
--basic: provides
basic Username and Password auth
·
--ntlm: windows auth
·
--digest: web server
negotiation through digest access
In the following example, I am
providing a list inline with two variables and --basic input to bruteforce a
website httpwatch.com
wfuzz -z
list,nonvalid-httpwatch --basic FUZZ:FUZZ https://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx
Recursive fuzz
-R switch can specify the levels
of recursion while fuzzing directories or parameters. Recursion in simple terms
means fuzzing at multiple different levels of directories like /dir/dir/dir etc
In the following example, we are
recursing at level 1 with a list inline containing 3 directories: admin, CVS
and cgi-bin. Note how a directory with - in its name can be supplied inline
wfuzz -z
list,"admin-CVS-cgi\-bin" -R1 http://testphp.vulnweb.com/FUZZ
Printers and output
Printers in wfuzz refers to all
the formats a payload’s output can be processed as. It can be viewed using -e
succeeded by printers argument. Furthermore, “-o” flag can specify the format
of the output too
wfuzz -e printers
wfuzz -o json -w
wordlist/general/common.txt http://testphp.vulnweb.com/FUZZ
Encoders
Various encoders are available in
wfuzz. One such encoder we saw earlier was md5. Other encoders can be viewed by
using “-e” flag with encoders argument.
wfuzz -e encoders
One can fuzz a website for
directories by using MD5 output like so:
wfuzz -z
file,wordlist/general/common.txt,md5 http://testphp.vulnweb.com/FUZZ
Storing and restoring fuzz from recipes
To make scanning easy, wfuzz can
save and restore sessions using the “--dump-recipe” and “--recipe” flag.
wfuzz -w
wordlist/general/common.txt --dump-recipe /tmp/recipe --sc 200,301
http://testphp.vulnweb.com/FUZZ
wfuzz --recipe
/tmp/recipe
Ignoring exceptions and errors
Often while fuzzing, there are
various errors and exceptions that a website can throw. “-Z” option can make
wfuzz ignore these errors and exceptions. First, we run a normal subdomain
fuzzing routine and then with -Z option:
wfuzz -z
list,support-web-none http://FUZZ.google.com/
wfuzz -z
list,support-web-none -Z http://FUZZ.google.com/
As you could see, -Z ignores that
error on the bottom. Further, any invalid response can also be hidden like so:
wfuzz -z
list,support-web-none -Z --hc “XXX” http://FUZZ.google.com/
Filtering results
There are many filters available
to manipulate a payload or output.
wfuzz --filter-help
These can be manipulated using
“--filter, --slice, --field and --efield” arguments.
For example, to view raw responses
of the payload sent and the complete HTTP request made, you can use “--efield
r” option
wfuzz -z range --zD
0-1 -u http://testphp.vulnweb.com/artists.php?artist=FUZZ --efield r
However, if only the intended URL
is needed, one can do it by providing --efield url input.
wfuzz -z range --zD
0-1 -u http://testphp.vulnweb.com/artists.php?artist=FUZZ --efield url --efield
h
Similarly, to filter out results
based on the response code and the length of the page (lines greater than 97),
you can do it like:
wfuzz -z range,0-10
--filter "c=200 and l>97" http://testphp.vulnweb.com/listproducts.php?cat=FUZZ
A detailed table of all the filters
for the payloads can be found here.
Sessions in wfuzz
A session in wfuzz is a temporary
file which can be saved and later picked up, re-processed and post-processed.
This is helpful in situations where one result saved already needs alterations
or an analyst needs to look for something in the results. “--oF” filter can
save the session output to a file.
wfuzz --oF
/tmp/session -z range,0-10 http://testphp.vulnweb.com/listproducts.php?cat=FUZZ
This session file can now be
opened up again and consumed using the “wfuzzp” payload like so:
wfuzz -z
wfuzzp,/tmp/session FUZZ
One such example of this
filteration from a previously saved
session is as follows where we find an SQL injection vulnerability by utilizing
a Pytho regex designed to read responses after a request modifies a parameter
by adding apostrophe (‘) and fuzzing again. “-A” displays a verbose output.
The regex r.params.get=+’\’ adds apostrophe (‘) in the get parameter. r
stands for raw response.
wfuzz -z range,1-5
--oF /tmp/session http://testphp.vulnweb.com/artists.php?artist=FUZZ
wfuzz -z
wfuzzp,/tmp/session --prefilter "r.params.get=+'\''" -A FUZZ
As you can see, request number 4
throws an SQL error which indicates SQL injection. For more regex operations
refer here.
Conclusion
Wfuzz is a versatile tool that
can perform more than just directory enumeration and truly help a pentester in
his analyses. It’s a fast scanner which is easy to use and coded in python for
portability. Hope you liked the article. Thanks for reading.
0 comments:
Post a Comment