Monday, December 13, 2010

Metasploit HTTP fuzzer v0.2 - Tutorial

The main idea of this post is give an overview of the fuzzer that I developed. I don't think it is an state of the art fuzzer. Actually, I think it is pretty dumb fuzzer but I feel it can help a lot if you know how to configure it and use metasploit at the same time.

To start using the fuzzer download the file from here and save it in the metasploit msf3 folder under "/modules/auxiliary/fuzzers/http/"

Start msfconsole and type: use auxiliary/fuzzers/http/http_fuzz

Now, starting with the basic, the options. This tool can provide different kind of fuzzing types depending on what the user needs. The main idea behind the tool is to help in the discovery of common problems on web applications and also help with the identification of vulnerabilities by fuzzing specific parameters. The following are the options that the fuzzer provides.



Some of this options I feel are self explanatory if you look at the description. However, some of this might not be so intuitive. Because of this I will explain with some examples.

Example 1 - NUMERIC Fuzzing (TYPE 1)
1. Configure fuzzing point
The first thing that you have to do is to pick the parameter of the application that you want to fuzz. You can do this by browsing through the application (using a proxy or not) and selecting the parameters that you want to test. In this example I will use the fuzzer just to discover specific valid pages on the application and identify valid pages. Lets say that we find a website that will allow the follow GET request: http://web_app/about/news?id=24 . Now, if we want to play with the id  parameter the only thing that we will have to do is configure the fuzzing point. On mfconsole type:

msf auxiliary(http_fuzz) > set VHOST web_app
VHOST => web_app
msf auxiliary(http_fuzz) > set RHOST host_IP
RHOST => host_IP
msf auxiliary(http_fuzz) > set PATH /about/news?id={X}24{X}
PATH => /about/news?id={X}24{X}


2. Configure METHOD

msf auxiliary(http_fuzz) > set METHOD GET
METHOD => GET


3. Configure TYPE of fuzzing - Now you just have to select the TYPE of fuzzing and depending on that other parameters will have to be configured. For this example we will select Numeric fuzzing.

msf auxiliary(http_fuzz) > set TYPE 1
TYPE => 1


4. Configure START and STOP

msf auxiliary(http_fuzz) > set START 24
START => 24
msf auxiliary(http_fuzz) > set STOP 100
STOP => 100


5. Start the fuzzer

msf auxiliary(http_fuzz) > run

[*] Fuzzing...
[*] Start number: 24
[*] Stop Number: 100
[*] Iterations 77
[*] No Headers provided
[*] No BODY was provided as a part of the request
[*] No Cookies were provided as a part of the request
[*] You need to create a database and connect to it if you the DATABASE option to work.
[*] Running fuzzer against http//ip_address/about/news?id={X}24{X}
[*] | ID | CODE |  LENGTH | RESP TIME | TEST VALUE

[*] | 1 |  302 |  350  | 0.348529465 | 24
[*] | 2 |  302 |  350  | 0.302565619 | 25
[*] | 3 |  302 |  350  | 0.377012325 | 26
[*] | 4 |  302 |  350  | 0.335730538 | 27
[*] | 5 |  302 |  350  | 0.399629274 | 28
[*] | 6 |  302 |  350  | 0.301453555 | 29
...
[*] | 77 |  302 |  350  | 0.301453555 | 100
[*] Auxiliary module execution completed
msf auxiliary(http_fuzz) > 


Example 2 - STRING Fuzzing (TYPE 2)
A similar kind of  fuzzing can be done using the STRING fuzzing (set TYPE 2). The only difference is that instead of providing numbers at the START and STOP options you will have to provide strings. For example:

msf auxiliary(http_fuzz) set START a
msf auxiliary(http_fuzz) set STOP zzzzz

This will basically go through all the string from a-zzzz on the selected parameter

Example 3 - CUSTOM Fuzzing (TYPE 3)
I will assume that selecting a fuzzing point and a method (GET or POST) are already explained in Example 1. For using the custom fuzzing option you just have to define the characters that you want to use during fuzzing. In this example it is assumed that the fuzzing point has been already selected.

1. Configure TYPE of fuzzing

msf auxiliary(http_fuzz) > set TYPE 3
TYPE = 3


2. Configure CHARS for fuzzing. The default CHARS to use while using this option are: abcdefghijklmnopqrstwxiz1234567890$%/(= . Look at the advanced options of this module to review them (show advanced)

msf auxiliary(http_fuzz) > show advanced

If you want to change this characters use the set CHARS command. For example:

msf auxiliary(http_fuzz) > set CHARS abc123&^$
CHARS => abc123&^$

3. Set the number of POSITIONS that you want the fuzzer to test. For example if you select only two CHARS ("ab") and two POSITIONS. The fuzzer will try the following strings: [a,b,ab,ba,aa,bb] . It is recommended that the number of positions matches the number of character provided by the user. This is the only way to provide all possible options.

msf auxiliary(http_fuzz) > set POSITIONS 3
POSITIONS => 3
msf auxiliary(http_fuzz) > set CHARS abc
CHARS => abc


4. Run the FUZZER over the specific parameters that you want to test. Remember to always enclose the parameter that you want to substitute on the request with: {X}PARAMETER{X}

msf auxiliary(http_fuzz) > run


Example 4 - FILE Fuzzing (TYPE 4)
I guess this option could be also called fuzzing using a file instead of "file fuzzing" to avoid confusions. I apologize if I made someone believe that this option is the typical file fuzzing .

FILE fuzzing is option '4' of the fuzzer. This option will basically allow you to choose a file that will contain a sequential list of all the words/characters/numbers or whatever thing makes sense to use for fuzzing. The idea of this options to allow the user to dynamically use any word list that they want to use. I have used this to discover files or directories on web servers but it can basically used depending on any situation that you want. Another way that I have used this I have put together a list of SQL injections or XSS commands and fuzz on an specific parameter. For a list of this that you can include in this file I recommend the tool created by Rsnake a couple o years ago: "NoMore1=1" (or something like that..)  At the end of the day it is up to you to imagine how to use this functionality...

A small example would be:

msf auxiliary(http_fuzz) > set TYPE 4
TYPE => 4
msf auxiliary(http_fuzz) > set PATH /{X}a{X}/
PATH => /{X}a{X}/
msf auxiliary(http_fuzz) > set RHOST host_ip
RHOST => IP_ADDRESS
msf auxiliary(http_fuzz) > set VHOST web_app.com
VHOST => IP_ADDRESS

msf auxiliary(http_fuzz) > set FILE wmap_dirs.txt
FILE => wmap_dirs.txt

msf auxiliary(http_fuzz) > run


[*] Fuzzing...
[*] Number of requests 2346
[*] No Headers provided
[*] No BODY was provided as a part of the request
[*] No Cookies were provided as a part of the request
[*] Running fuzzer against http//IP_ADDRESS/{X}a{X}/
[*] | ID | CODE |  LENGTH | RESP TIME | TEST VALUE

[*] | 1 |  404 |  1635  | 0.125380119 | 0
[*] | 2 |  404 |  1635  | 0.140205328 | 00001
[*] | 3 |  404 |  1635  | 0.137170723 | 0001
[*] | 4 |  404 |  1635  | 0.15165385 | .CVS
[*] | 5 |  404 |  1635  | 0.134547762 | ...
[*] | 6 |  404 |  1635  | 0.150078353 | 0day
[*] | 7 |  404 |  1635  | 0.147979133 | 001
[*] | 8 |  404 |  1635  | 0.151717669 | 1
[*] | 9 |  404 |  1635  | 0.152698101 | 007
[*] | 10 |  404 |  1635  | 0.184284936 | 04
.
.
... and so on

Example 5 - RADOM CHARS Fuzzing (TYPE 5)
Although this option might seem repetitive I believe it is not, I'll explain. Sometimes when you are looking for specific vulnerabilities in an web application it is easier to use random characters in a number of parameters and identify how the application responds to them. This will help the attacker to identify injection points (sql or XSS) or other any strange behavior on the application such as redirections. Although this same type of fuzzing might be accomplished by configuring option '3' of the fuzzer I though it come really handy to have it just by changing the fuzzing type.

msf auxiliary(http_fuzz) > set TYPE 5
msf auxiliary(http_fuzz) > set PATH /eng/News.asp?id={X}a{X}
PATH => /eng/News.asp?id={X}a{X}
msf auxiliary(http_fuzz) > set RHOST host_ip
RHOST => IP_ADDRESS
msf auxiliary(http_fuzz) > set VHOST web_app.com
VHOST => IP_ADDRESS
msf auxiliary(http_fuzz) > run

[*] Fuzzing...
[*] Number of requests 185372
[*] No Headers provided
[*] No BODY was provided as a part of the request
[*] No Cookies were provided as a part of the request
[*] Running fuzzer against http//ip_address/eng/News.asp?id={X}a{X}
[*] | ID | CODE |  LENGTH | RESP TIME | TEST VALUE

[*] | 1 |  200 |  133  | 0.544628639 | '
[*] | 2 |  200 |  17922  | 0.662964496 | /
[*] | 3 |  200 |  17922  | 0.693027466 | |
[*] | 4 |  200 |  17922  | 0.712019893 | "
.
.
... and so on

In this specific example although we get as a response a HTTP CODE 200 when you look at the LENGTH column you can see that something is happening in the application when we use the ' (single column) character. That is the main purpose of this option; identify the character that might lead to an injection or something worth to look further more.


Example 6 -SQL injection Fuzzing (TYPE 6)
The main purpose of this options is to use it once you already detected an injection point and run it on that parameter just. I mean in my opinion this is straight forward. Set the fuzzing parameter and run the module. In order for this option to work you can have to download the sql_injections file that is in the site where and save it under the msf directory /msf3/data/wordlists/. Go here if you want to download it.

msf auxiliary(http_fuzz) > set TYPE 6
TYPE => 6
msf auxiliary(http_fuzz) > set PATH /english/news.php?id=48{X}a{X}

msf auxiliary(http_fuzz) > run

[*] Fuzzing...
[*] Number of requests 151
[*] No Headers provided
[*] No BODY was provided as a part of the request
[*] No Cookies were provided as a part of the request
[*] Running fuzzer against http//host_ip/english/news.php?id=48{X}a{X}
[*] | ID | CODE |  LENGTH | RESP TIME | TEST VALUE

[*] | 1 |  200 |  8792  | 0.369505342 | ' or 'one'='one
[*] | 1 |  200 |  8792  | 0.417652944 | ' and 'one'='one
[*] | 1 |  200 |  11846  | 0.493800398 | and 1=1
[*] | 1 |  200 |  11846  | 0.537422557 | ' or 'one'='one--
[*] | 1 |  200 |  11846  | 0.598660924 | and 1=1--


Example 7 - LONG Strings (TYPE 7)
This is basically a regular dumb fuzzing type. With this option the only thing that you have to do is define the parameter to be fuzzed, define the STEP (number of characters increased every request) and the DEPTH (maximum number of characters to be used). NOTE:  STEP<= DEPTH

msf auxiliary(http_fuzz) > set TYPE 7
TYPE => 7
msf auxiliary(http_fuzz) > set PATH /english/news.php?id={X}a{X}
PATH => /english/news.php?id={X}a{X}
msf auxiliary(http_fuzz) > set DEPTH 1000
DEPTH => 1000
msf auxiliary(http_fuzz) > set STEP 10
STEP => 10
msf auxiliary(http_fuzz) > run

[*] Fuzzing...
[*] Number of requests 101
[*] No Headers provided
[*] No BODY was provided as a part of the request
[*] No Cookies were provided as a part of the request
[*] Running fuzzer against http//host_ip/english/news.php?id={X}a{X}
[*] | ID | CODE |  LENGTH | RESP TIME | TEST VALUE

[*] | 1 |  200 |  8611  | 0.331915432 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[*] | 2 |  200 |  8611  | 0.334508011 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[*] | 3 |  200 |  8611  | 0.351879703 | XXXXXXXXXXXXXXXXXXXX
[*] | 4 |  200 |  8611  | 0.41747247 | X
[*] | 5 |  200 |  8611  | 0.442105074 | XXXXXXXXXX
[*] | 6 |  200 |  8611  | 0.318690562 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[*] | 7 |  200 |  8611  | 0.326300747 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[*] | 8 |  200 |  8611  | 0.361352691 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

NOTE:* During this fuzzing option the advanced option PRINT_PARAM might come handy. Look at the end of this post for the description of advanced options.


Example 8 -TRANSVERSAL Fuzzing (TYPE 8)
The last option is also straight forward. This will do a transversal fuzzing where the fuzzing parameter is defined.  

msf auxiliary(http_fuzz) > set TYPE 8
TYPE => 8
msf auxiliary(http_fuzz) > set PATH /{X}a{X}
PATH => /{X}a{X}
msf auxiliary(http_fuzz) > set DEPTH 1000
DEPTH => 1000
msf auxiliary(http_fuzz) > set STEP 10
STEP => 10
msf auxiliary(http_fuzz) > run

[*] Fuzzing...
[*] Number of requests 84
[*] No Headers provided
[*] No BODY was provided as a part of the request
[*] No Cookies were provided as a part of the request
[*] Running fuzzer against http//host_ip/{X}a{X}
[*] | ID | CODE |  LENGTH | RESP TIME | TEST VALUE

[*] | 1 |  400 |  226  | 0.236811028 | ..\
[*] | 2 |  400 |  226  | 0.250760777 | %2e2e%2f
[*] | 3 |  400 |  226  | 0.22901241 | %2e2e%5c
[*] | 4 |  400 |  226  | 0.246130438 | ..%255c
[*] | 5 |  400 |  226  | 0.240181706 | ../
[*] | 6 |  400 |  226  | 0.163898769 | ..%u2216
[*] | 7 |  404 |  228  | 0.168686738 | ..\..\..\..\..\..\..\..\..\..\
[*] | 8 |  400 |  226  | 0.173574304 | %2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c
[*] | 9 |  400 |  226  | 0.183728038 | %2e2e%2f%2e2e%2f%2e2e%2f%2e2e%2f%2e2e%2f%2e2e%2f%2e2e%2f%2e2e%2f%2e2e%2f%2e2e%2f
[*] | 10 |  400 |  226  | 0.198060237 | ../../../../../../../../../../
[*] | 11 |  404 |  278  | 0.157729548 | %2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c%2e2e%5c
[*] | 12 |  400 |  226  | 0.163983692 | ..%u2216..%u2216..%u2216..%u2216..%u2216..%u2216..%u2216..%u2216..%u2216..%u2216
[*] | 13 |  400 |  226  | 0.160496726 | ../../../../../../../../../../../../../../../../../../../../
.
.
.
and so on

Database Support
I hate doing this but this is not yet supported. Although this is something that I feel it is awesome about mestaploit and I want to use it for this tool I have not been able to store all the responses in the database without raising exceptions on the encoding. When I fix this bug I will put a complete tutorial on the support of this. The main idea will be to do:

set DATABASE true
db_connect user@DATABASE

and from this pront forward everything will be stored on a database that later on you can use for reference.

If you have an idea or have gone through this problem a solution will be greatly appreciated and payed with a beer at Defcon.

NOTE: If you want to enable database support please on the metasploit console write: gem install htmlentities

Advanced options explained
Almost all metasploit modules have advanced options that should be considered while running them. This is not the exception (command:"show advanced"). The following are the options that will allow the user to have a more fitted fuzzing.

CODE and USE_HTTP_CODE

This option will make the fuzzer to display on the console only the error code that you are interested in (e.g. 500). Usually when an injection point or something else interesting in the application is identified the web server will return an internal error code: 500. That is why this is the default value in this tool. However, as you might already know you can configure the webserver to return only specific codes. That is why you can choose whatever code makes more sense to you and the application you are testing: 302, 200, 401, etc

Name           : USE_HTTP_CODE
Current Setting: false
Description    : Only display HTTP responses that with an specific HTTP code


Name           : CODE

Current Setting: 500
Description    : Response HTTP code to display during fuzzing. . e.g. 500



PHRASE
This option allows you to search for specific phrase on the response while fuzzing a web server. Lets say that you are looking for an error based injection and you are only concerned when the response from the server contains the following text: "
Warning: mysql_num_rows()". The only thing that you have to do is to set the PHRASE to that specific text that you are looking for. This is only an example but it can also be helpful to search for specific thing on javascript.



Name           : PHRASE
Current Setting: 
Description    : Phrase or string to look for in the response body


PRINT_PARAM
This option allows you to configure the fuzzer to not print the test parameter that it using on each request. This is incredibly helpful when you use options number 7 or 8 (LONG STRINGS or TRANSVERSAL) which will basically print a lot of character on the console.

Name           : PRINT_PARAM
Current Setting: true
Description    : Print fuzz parameneter on the status.

THREADS
Number of threads that you want to use while fuzzing. The default number is 5 although you can set it up to whatever number you want. Please be careful if you play with this option since this will consume a significant amount of memory if you set it to a bigger number.

Name           : THREADS
Current Setting: 5
Description    : Number of Threads


Again, I hope this helps someone. 

c4an.