Web Application Fuzz Testing Tool


This project is for individuals.

One of the most helpful tools that a security-minded software developer can have is a fuzz-testing tool, or a fuzzer. A fuzzer is a type of exploratory testing tool used for finding weaknesses in a program by scanning its attack surface.

The best fuzzers are highly customizable, so generalized fuzzers are often quite complex to configure and use, and can become out-of-date quickly. Fortunately, we're software engineers, so we'll build a fuzzer that can be customized to a specific web application rapidly.


You have two choices of programming language: Ruby or Python. You may choose the specific packages to use - research them and find ones that fit your needs (there are many for both languages). For Ruby, successful projects have used Ruby with Mechanize, or Python with the Requests package or Mechanical Soup, or Scrapy. If you are using Python, past students strongly recommend Python3+ due to some inconsistencies in the 2.7 versions of packages (i.e. use "python3" and "pip3" to run).

Think of the above libraries like a GUI-less browser - it can simulate everything that a browser does, but programmatically. It does HTTP requests, parses HTML, and a lot more. In particular, they will:

Your code will be tested against a modified version of the DVWA we provided in the web application activity. We recommend you use DVWA as your test bed, but make sure your code is general enough to work on any website.

Ruby Mechanize Example

This example demonstrates a quick script for getting the links from our course web page using Ruby and the Mecahnize gem.

Command-Line interaction

Your fuzzer must run from the command line. Depending on your language, your exact command might vary (e.g. python fuzz.py or ruby fuzz.rb), but the basic structure should follow this manpage:

fuzz [discover | test] url OPTIONS

  discover  Output a comprehensive, human-readable list of all discovered inputs to the system. Techniques include both crawling and guessing.
  test      Discover all inputs, then attempt a list of exploit vectors on those inputs. Report potential vulnerabilities.

  --custom-auth=string     Signal that the fuzzer should use hard-coded authentication for a specific application (e.g. dvwa). Optional.

  Discover options:
    --common-words=file    Newline-delimited file of common words to be used in page guessing. Required.

  Test options:
    --vectors=file         Newline-delimited file of common exploits to vulnerabilities. Required.
    --sensitive=file       Newline-delimited file data that should never be leaked. It's assumed that this data is in the application's database (e.g. test data), but is not reported in any response. Required.
    --random=[true|false]  When off, try each input to each page systematically.  When on, choose a random page, then a random input field and test all vectors. Default: false.
    --slow=500             Number of milliseconds considered when a response is considered "slow". Default is 500 milliseconds

  # Discover inputs
  fuzz discover http://localhost:8080 --common-words=mywords.txt

  # Discover inputs to DVWA using our hard-coded authentication
  fuzz discover http://localhost:8080 --common-words=mywords.txt

  # Discover and Test DVWA without randomness
  fuzz test http://localhost:8080 --custom-auth=dvwa --common-words=words.txt --vectors=vectors.txt --sensitive=creditcards.txt --random=false

Expected Output

Your output should be human readable. Think of it like a build report you might get in an email that you can review from time to time. It should be detailed enough that you can look into potential vulnerabilities, and it should also be readable enough that you're not parsing through HTTP outputs and log messages

An example of good output for discovercan be found here. (You do not need to match this format exactly.) An example of good output from test can be found here. Note that DVWA evolves over time, so these exact outputs may be slightly different than yours - these are just examples, not oracles.

Submission Instructions

You must use RIT's installation of GitLab for this project. By a pre-determined date (given by your instructor), please do the following:

  1. Go to https://kgcoe-git.rit.edu
  2. Create a new account with them using your RIT login (if you don't have one already)
  3. Create a new project - be sure to have the word "fuzzer" in the title. Visibility is Private (please do not share your code, even after this class has finished).
  4. On the project settings page (gear icon in the upper-right), go to the Members. Add your instructor and the TA as Reporter of your project. (If you need the instructor's and/or TA's RIT username, you can find it on myCourses.)

You are required to push your code to this repository by the deadline. At each deadline, we will autmatically pull the code and grade that. You do not need a separate repository for each release - just keep working on the same repository for the entire fuzzer project. If you need a specific version to be graded (i.e. one that is not the most recent as of the deadline), contact your TA and they will make sure to check out the right one. We will assume the master branch is your submission.

Please include a file called .gitlab-ci.yml (note the dot at the beginning of the file name) in the root of your repository. Here is the base file you should use, but then adapt it to your configuration. Note that YML files don't like tabs as whitespace and are finicky about number of spaces for indentation.

image: andymeneely/swen331fuzzer
    # do not change any of the statements in this section
    - service apache2 start
    - mysql_install_db --user=mysql -ldata=/var/lib/mysql
    - service mysql start
    - /usr/bin/mysqladmin -u root password fuzzer
    - service mysql restart
    - /mysql-setup.sh
    # do not change any of the statements in this section
    # here is where you can write your commands to run your fuzzer or any custom setup commands
    - echo "hello class"
    # need some example files for vectors and words? These are on the image
    - cat /words.txt
    - cat /vectors.txt
    # An example fuzzer command. Note the url is DIFFERENT than XAMPP example (no /dvwa).
    - ruby fuzzer.rb discover http://localhost/ --custom-auth=dvwa
  stage: test

This is a continuous integration configuration file. Every commit you push to the repository, your fuzzzer will be run against DVWA installed in a clean environment. To see the output, go to GitLab and find your build in the "Pipelines" page. You are strongly encouraged to keep an eye on this output to make sure your code is working as expected as you work.

Your application should be easy to use from a customer's perspective. Some notes about your submision include:

Part 0: --custom-auth

For this initial part, you will need to implement --custom-auth to log into DVWA.

For this product, DVWA is the main application you must authenticate to, but this fuzzer should work on any web application too. The code within the DVWA custom auth module of your program can be hardcoded. You are welcome to add other customizations for other products to test your fuzzer further (e.g. your senior project). With custom authentication turned off, the fuzzer should just crawl the exterior of the webapp (perhaps get lucky if the vector list had a password).

You cannotassume that DVWA will be installed on a specific server, in a specific folder, on a specific port. For example, http://example.com:1234/foo/dvwa is a valid url we might try.

Be sure to document in your README any setup you need.

To demonstrate you are logged in, just print out the contents of the HTML of the DVWA home page, after loggin in, to stdout. (Remove this output for future rounds).

Part 1: fuzz discover

On the discovery side, your fuzzer will need to discover as many potential inputs to the system as possible. It will need to do the following:

Part 2: fuzz test

Once you're done with input discovery, it's time to test. Testing has two parts: trying vectors, and then determining if the outcome was out of the ordinary.

To conduct your test, you must use an external list of fuzz vectors. These are strings of common exploits to vulnerabilities. These lists can be found all over the internet. This list at OWASP is a fine place to start. TIP: when developing, keep this list short and targeted. You're fuzzing applications you know are vulnerable, so unnecessary vectors can slow your Edit-Compile-Test cycle.

Upon sending in the vector, you'll need examine the response to see if the page may have a vulnerability. Here are some reasons, and you may think of more.


Given that we are fuzzing known vulnerable applications, we will run your fuzzer to ensure that it reports errors on those vulnerabilities. However, your fuzzer should not hardcode specific vulnerabilities in specific applications - the point of this exercise is to make your fuzzer discover potential vulnerabilities. The grading breakdown is as follows:


Submit your source code via GitLab. We will pull from the master branch at the deadline. Write up a basic README on getting the code to run in other environments.