Grinder is a system to automate the fuzzing of web browsers and the management of a large number of crashes. Grinder Nodes provide an automated way to fuzz a browser, and generate useful crash information (such as call stacks with symbol information as well as logging information which can be used to generate reproducible test cases at a later stage). A Grinder Server provides a central location to collate crashes and, through a web interface, allows multiple users to login and manage all the crashes being generated by all of the Grinder Nodes.
A Grinder Node requires a 32/64 bit Windows system and Ruby 2.0 (Ruby 1.9 is also supported but you wont be able to fuzz 64bit targets).
A Grinder Server requires a web server with MySQL and PHP. You can use Docker to setup and start the enviroment using the following steps:
Install docker-compose (considering you already have Docker installed):
$ sudo -H pip install docker-compose
Run Grinder Server using:
$ docker-compose up -d
Grinder Server features:
-
Multi user web application. User can login and manage all crashes reported by the Grinder Nodes. Administrators can create more users and view the login history.
-
Users can view the status of the Grinder system. The activity of all nodes in the system is shown including status information such as average testcases being run per minute, the total crashes a node has generated and the last time a node generated a crash.
-
Users can view all of the crashes in the system and sort them by node, target, fuzzer, type, hash, time or count.
-
Users can view crash statistics for the fuzzers, including total and unique crashes per fuzzer and the targets each fuzzer is generating crashes on.
-
Users can hide all duplicate crashes so as to only show unique crashes in the system in order to easily manage new crashes as they occur.
-
Users can assign crashes to one another as well as mark a particular crash as interesting, exploitable, uninteresting or unknown.
-
Users can store written notes for a particular crash (viewable to all other users) to help manage them.
-
Users can download individual crash log files to help debug and recreate testcases.
-
Users can create custom filters to exclude uninteresting crashes from the list of crashes.
-
Users can create custom e-mail alerts to alert them when a new crash comes into the system that matches a specific criteria.
-
Users can change their password and e-mail address on the system as well as view their own login history.
Grinder Node features:
-
A node can be brought up and begin fuzzing any supported browser via a single command.
-
A node injects a logging DLL into the target browser process to help the fuzzers perform logging in order to recreate testcases at a later stage.
-
A node records useful crash information such as call stack, stack dump, code dump and register info and also includes any available symbol information.
-
A node can automatically encrypt all crash information with an RSA public key.
-
A node can automatically report new crashes to a remote Grinder Server.
-
A node can run largely unattended for a long period of time.
Grinder does not include any fuzzers for the Grinder Nodes and you will need to write your own. However a very simple example fuzzer is included (.\grinder\node\fuzzer\SimpleExample.html) to show how to begin writing suitable fuzzers for use with Grinder.
Installing a Grinder server requires a web server with PHP and MySQL.
-
Copy the contents of .\grinder\server\ over the the web server.
-
Create a MySQL database and associated user.
-
Surf over to the install.php page to complete the installation.
-
When installing, the 'Grinder Key' used must be the same as the one written in all the Grinder Nodes config.rb files (see below).
-
After successful installation, you can login and view all of the running nodes and all of the crashes generated.
For a detailed step by step guide to install a Grinder Node please refer to the following wiki page:
https://github.com/stephenfewer/grinder/wiki/Installing-a-Grinder-Node
For a quick start, the steps for installing a node are as follows:
-
Install Ruby (www.ruby-lang.org). Ruby 2.0 x64 can fuzz both 32bit and 64bit targets. Ruby 2.0 x86 and Ruby 1.9 x86 can only fuzz 32bit targets.
-
On a 32bit Windows system: Copy '.\grinder\node\data\x86\grinder_logger.dll' to 'c:\windows\system32'
-
On a 64bit Windows system: Copy '.\grinder\node\data\x86\grinder_logger.dll' to 'c:\windows\syswow64'
-
On a 64bit Windows system: Copy '.\grinder\node\data\x64\grinder_logger.dll' to 'c:\windows\system32'
-
Create a folder for symbol files to be stored, e.g. 'c:\symbols'
-
Edit the config.rb file to suit your setup. Please see the default config.rb file for a description of the various options. You may create multiple config files if you intend on running more than one node on a system, (e.g. config_g1.rb, config_g2.rb). You can then specify on the command line which config file to use when bringing up the node. If you have setup a Grinder server, use the same Grinder Key and the appropriate server URL so the node can communicate with the Grinder server.
-
Finally to run the node issue a Ruby command as shown below where the browser parameter is the browser you want to fuzz (e.g. IE, FF or CM).
.\grinder\node>ruby grinder.rb [--config=c:\path\to\alternative\config.rb] --browser=BROWSER
When a Grinder Node generates a crash in a browser, two files are created within the .\grinder\node\crashes\ directory. The contents of these files are also transmitted to the remote Grinder Server. The .crash file contains useful debugging information (call stack, disassembly, register info, and so on), while the .log file contains the logging information generated by the fuzzer which can be used to generate a reproducible testcase so you can trigger the crash again. As this information is sensitive in nature it is useful (and recommended) to encrypt it.
A Grinder Node can be configured to use an RSA public key to encrypt this information for storage both locally on the respective Node as well as for transmission and storage on the Grinder Server. Simply generate a suitable public key (details below) and edit the config.rb to use this key. Now when you download the crash/log files from the Grinder Server you will need to decrypt them before you can use them.
To generate a suitable key pair you can use the included crypto.rb utility:
.\grinder\node>ruby crypto.rb /generate /pubkey public.pem /privkey private.pem [/keysize 4096] [/keypass MyKeYpAsSwOrD]
The generated public key will need to be copied over to all the Grinder Nodes while the private key will need to be stored securely on the analyst's workstations.
To decrypt an encrypted crash/log file you can then use the following command:
.\grinder\node>ruby crypto.rb /decrypt /privkey private.pem /inputfile XXXXXXXX.XXXXXXXX.crash [/outputfile plaintext.txt] [/keypass MyKeYpAsSwOrD]
When you have generated a crash and downloaded the log/crash files you can use the testcase.rb utility to transform the .log file into a html file that will (hopefully) reproduce the crash.
.\grinder\node>ruby testcase.rb [--config=c:\path\to\CONFIG.RB] --log=c:\path\to\XXXXXXXX.XXXXXXXX.log --save=c:\path\to\XXXXXXXX.XXXXXXXX.html
If the log file has been automatically encrypted, you can pass in a private key (and optional keypass) to testcase.rb in order to decrypt the log file on the fly:
.\grinder\node>ruby testcase.rb [--config=c:\path\to\CONFIG.RB] --log=c:\path\to\XXXXXXXX.XXXXXXXX.log --save=c:\path\to\XXXXXXXX.XXXXXXXX.html --key=c:\path\to\PRIVATE.PEM --keypass=PASSPHRASE
Depending on how you write your fuzzers you may need to modify testcase.rb to suit or edit the testcase options ($testcase_opts) in your config file.
If the testcase does not reproduce the crash it is useful to create an 'Alert' within the Grinder Server to alert you by email whenever the same crash is encountered again. Using a different log file for the same crash may help reproduce it.
The latest source code for Grinder can be found at https://github.com/stephenfewer/grinder
Please file all bug reports via GitHub at the following address: https://github.com/stephenfewer/grinder/issues
Please submit all code contributions as pull requests via GitHub, thanks!.
If you find Grinder useful, please consider a Bitcoin donation to 12cS37zQSvAGEokQJfWzhwyeGPBA2SwCxQ, thanks!
Grinder is licensed under a 3 clause BSD license. Please see the full text of this license in the .\grinder\LICENSE.txt file.
The following libraries are included with Grinder and are licensed separately as follows:
- Metasm is licensed under a GNU Lesser General Public License (Please see .\grinder\node\lib\metasm\LICENCE)
- JQuery is licensed under the MIT license (Please see http://jquery.org/license)
- jqPlot is licensed under the MIT license (Please see http://www.jqplot.com/info.php)
- JQuery UI is licensed under the MIT license (Please see http://jquery.org/license)
- jQuery Cookie plugin is licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
- dbghelp.dll (v6.2.9200.20512) and symsrv.dll (v6.2.9200.20512) are re-distributable libraries from the Microsoft Debugging Tools for Windows. (Please see .\grinder\node\data\debugging_tools_license.txt)