diff --git a/main.go b/main.go index 8bb499a..ffdeef5 100644 --- a/main.go +++ b/main.go @@ -17,17 +17,15 @@ import ( ) type cliOptions struct { - filterStatus string - filterSize string - filterReflect string - filterRegex string - filterWords string - matcherStatus string - matcherSize string - matcherReflect string - matcherRegex string - matcherWords string - headers headerFlags + filterStatus string + filterSize string + filterRegexp string + filterWords string + matcherStatus string + matcherSize string + matcherRegexp string + matcherWords string + headers headerFlags } type headerFlags []string @@ -52,19 +50,17 @@ func main() { flag.BoolVar(&conf.TLSSkipVerify, "k", false, "Skip TLS identity verification (insecure)") flag.StringVar(&opts.filterStatus, "fc", "", "Filter HTTP status codes from response") flag.StringVar(&opts.filterSize, "fs", "", "Filter HTTP response size") + flag.StringVar(&opts.filterRegexp, "fr", "", "Filter regexp") flag.StringVar(&opts.filterWords, "fw", "", "Filter by amount of words in response") flag.StringVar(&conf.Data, "d", "", "POST data.") flag.BoolVar(&conf.Colors, "c", false, "Colorize output.") - //flag.StringVar(&opts.filterRegex, "fr", "", "Filter regex") - //flag.StringVar(&opts.filterReflect, "fref", "", "Filter reflected payload") flag.StringVar(&opts.matcherStatus, "mc", "200,204,301,302,307,401", "Match HTTP status codes from respose") flag.StringVar(&opts.matcherSize, "ms", "", "Match HTTP response size") + flag.StringVar(&opts.matcherRegexp, "mr", "", "Match regexp") flag.StringVar(&opts.matcherWords, "mw", "", "Match amount of words in response") - //flag.StringVar(&opts.matcherRegex, "mr", "", "Match regex") flag.StringVar(&conf.Method, "X", "GET", "HTTP method to use.") flag.BoolVar(&conf.Quiet, "s", false, "Do not print additional information (silent mode)") flag.IntVar(&conf.Threads, "t", 20, "Number of concurrent threads.") - //flag.StringVar(&opts.matcherReflect, "mref", "", "Match reflected payload") flag.Parse() if err := prepareConfig(&opts, &conf); err != nil { fmt.Fprintf(os.Stderr, "Encountered error(s): %s\n", err) @@ -164,6 +160,11 @@ func prepareFilters(parseOpts *cliOptions, conf *ffuf.Config) error { errlist = multierror.Append(errlist, err) } } + if parseOpts.filterRegexp != "" { + if err := addFilter(conf, "regexp", parseOpts.filterRegexp); err != nil { + errlist = multierror.Append(errlist, err) + } + } if parseOpts.filterWords != "" { if err := addFilter(conf, "word", parseOpts.filterWords); err != nil { errlist = multierror.Append(errlist, err) @@ -179,6 +180,11 @@ func prepareFilters(parseOpts *cliOptions, conf *ffuf.Config) error { errlist = multierror.Append(errlist, err) } } + if parseOpts.matcherRegexp != "" { + if err := addMatcher(conf, "regexp", parseOpts.matcherRegexp); err != nil { + errlist = multierror.Append(errlist, err) + } + } if parseOpts.matcherWords != "" { if err := addMatcher(conf, "word", parseOpts.matcherWords); err != nil { errlist = multierror.Append(errlist, err) diff --git a/pkg/filter/filter.go b/pkg/filter/filter.go index bcdc53f..c9041ac 100644 --- a/pkg/filter/filter.go +++ b/pkg/filter/filter.go @@ -16,5 +16,8 @@ func NewFilterByName(name string, value string) (ffuf.FilterProvider, error) { if name == "word" { return NewWordFilter(value) } + if name == "regexp" { + return NewRegexpFilter(value) + } return nil, fmt.Errorf("Could not create filter with name %s", name) } diff --git a/pkg/filter/regex.go b/pkg/filter/regex.go new file mode 100644 index 0000000..6a745a0 --- /dev/null +++ b/pkg/filter/regex.go @@ -0,0 +1,29 @@ +package filter + +import ( + "fmt" + "regexp" + + "github.com/ffuf/ffuf/pkg/ffuf" +) + +type RegexpFilter struct { + Value *regexp.Regexp + valueRaw string +} + +func NewRegexpFilter(value string) (ffuf.FilterProvider, error) { + re, err := regexp.Compile(value) + if err != nil { + return &RegexpFilter{}, fmt.Errorf("Size filter or matcher (-fs / -ms): invalid value: %s", value) + } + return &RegexpFilter{Value: re, valueRaw: value}, nil +} + +func (f *RegexpFilter) Filter(response *ffuf.Response) (bool, error) { + return f.Value.Match(response.Data), nil +} + +func (f *RegexpFilter) Repr() string { + return fmt.Sprintf("Regexp: %s", f.valueRaw) +}