Empty filter (#330)

* add support to filter empty result files.

* update readme

* add contributors.

* add changelog

* Update ffufrc.example
This commit is contained in:
Bp0lr 2020-11-23 18:39:06 +00:00 committed by GitHub
parent c6a6293499
commit bc5e61ecc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 32 additions and 1 deletions

View File

@ -6,6 +6,7 @@
- Ffuf now reads a default configuration file `$HOME/.ffufrc` upon startup. Options set in this file
are overwritten by the ones provided on CLI.
- Change banner logging to stderr instead of stdout.
- New CLI flag `-or` to avoid creating result files if we didn't get any.
- Changed
- Pre-flight errors are now displayed also after the usage text to prevent the need to scroll through backlog.

View File

@ -1,5 +1,6 @@
# Contributors
* [AverageSecurityGuy](https://github.com/averagesecurityguy)
* [bp0](https://github.com/bp0lr)
* [bjhulst](https://github.com/bjhulst)
* [bsysop](https://twitter.com/bsysop)
* [ccsplit](https://github.com/ccsplit)

View File

@ -195,6 +195,7 @@ OUTPUT OPTIONS:
-o Write output to file
-od Directory path to store matched results to.
-of Output file format. Available formats: json, ejson, html, md, csv, ecsv (or, 'all' for all formats) (default: json)
-or Don't create the output file if we don't have results
EXAMPLE USAGE:
Fuzz file paths from wordlist.txt, match all responses but filter out those with content-size 42.

View File

@ -60,6 +60,7 @@
outputdirectory = "/tmp/rawoutputdir"
outputfile = "output.json"
outputformat = "json"
outputcreateemptyfile = false
[filter]
lines = ""

View File

@ -96,7 +96,7 @@ func Usage() {
Description: "Options for output. Output file formats, file names and debug file locations.",
Flags: make([]UsageFlag, 0),
Hidden: false,
ExpectedFlags: []string{"debug-log", "o", "of", "od"},
ExpectedFlags: []string{"debug-log", "o", "of", "od", "or"},
}
sections := []UsageSection{u_http, u_general, u_compat, u_matcher, u_filter, u_input, u_output}

View File

@ -58,6 +58,7 @@ func ParseFlags(opts *ffuf.ConfigOptions) *ffuf.ConfigOptions {
flag.BoolVar(&ignored, "compressed", true, "Dummy flag for copy as curl functionality (ignored)")
flag.BoolVar(&ignored, "i", true, "Dummy flag for copy as curl functionality (ignored)")
flag.BoolVar(&ignored, "k", false, "Dummy flag for backwards compatibility")
flag.BoolVar(&opts.Output.OutputCreateEmptyFile, "or", opts.Output.OutputCreateEmptyFile, "Don't create the output file if we don't have results")
flag.BoolVar(&opts.General.AutoCalibration, "ac", opts.General.AutoCalibration, "Automatically calibrate filtering options")
flag.BoolVar(&opts.General.Colors, "c", opts.General.Colors, "Colorize output.")
flag.BoolVar(&opts.General.Quiet, "s", opts.General.Quiet, "Do not print additional information (silent mode)")

View File

@ -32,6 +32,7 @@ type Config struct {
OutputDirectory string `json:"outputdirectory"`
OutputFile string `json:"outputfile"`
OutputFormat string `json:"outputformat"`
OutputCreateEmptyFile bool `json:"OutputCreateEmptyFile"`
ProgressFrequency int `json:"-"`
ProxyURL string `json:"proxyurl"`
Quiet bool `json:"quiet"`

View File

@ -75,6 +75,7 @@ type OutputOptions struct {
OutputDirectory string
OutputFile string
OutputFormat string
OutputCreateEmptyFile bool
}
type FilterOptions struct {
@ -140,6 +141,7 @@ func NewConfigOptions() *ConfigOptions {
c.Output.OutputDirectory = ""
c.Output.OutputFile = ""
c.Output.OutputFormat = "json"
c.Output.OutputCreateEmptyFile = false
return c
}
@ -374,6 +376,7 @@ func ConfigFromOptions(parseOpts *ConfigOptions, ctx context.Context, cancel con
conf.InputMode = parseOpts.Input.InputMode
conf.OutputFile = parseOpts.Output.OutputFile
conf.OutputDirectory = parseOpts.Output.OutputDirectory
conf.OutputCreateEmptyFile = parseOpts.Output.OutputCreateEmptyFile
conf.IgnoreBody = parseOpts.HTTP.IgnoreBody
conf.Quiet = parseOpts.General.Quiet
conf.StopOn403 = parseOpts.General.StopOn403

View File

@ -12,6 +12,11 @@ import (
var staticheaders = []string{"url", "redirectlocation", "position", "status_code", "content_length", "content_words", "content_lines", "resultfile"}
func writeCSV(config *ffuf.Config, res []Result, encode bool) error {
if(config.OutputCreateEmptyFile && (len(res) == 0)){
return nil
}
header := make([]string, 0)
f, err := os.Create(config.OutputFile)
if err != nil {

View File

@ -176,6 +176,10 @@ func colorizeResults(results []Result) []Result {
func writeHTML(config *ffuf.Config, results []Result) error {
if(config.OutputCreateEmptyFile && (len(results) == 0)){
return nil
}
results = colorizeResults(results)
ti := time.Now()

View File

@ -36,6 +36,11 @@ type jsonFileOutput struct {
}
func writeEJSON(config *ffuf.Config, res []Result) error {
if(config.OutputCreateEmptyFile && (len(res) == 0)){
return nil
}
t := time.Now()
outJSON := ejsonFileOutput{
CommandLine: config.CommandLine,

View File

@ -22,6 +22,10 @@ const (
func writeMarkdown(config *ffuf.Config, res []Result) error {
if(config.OutputCreateEmptyFile && (len(res) == 0)){
return nil
}
ti := time.Now()
keywords := make([]string, 0)

View File

@ -210,6 +210,10 @@ func (s *Stdoutput) writeToAll(config *ffuf.Config, res []Result) error {
// Go through each type of write, adding
// the suffix to each output file.
if(config.OutputCreateEmptyFile && (len(res) == 0)){
return nil
}
s.config.OutputFile = BaseFilename + ".json"
err = writeJSON(s.config, s.Results)
if err != nil {