Added regexp filter / matcher

This commit is contained in:
Joona Hoikkala 2018-11-12 19:47:49 +02:00
parent 1a8bcdfdfc
commit 8b2291dcfe
No known key found for this signature in database
GPG Key ID: D5AA86BBF9B29A5C
3 changed files with 53 additions and 15 deletions

22
main.go
View File

@ -19,13 +19,11 @@ import (
type cliOptions struct { type cliOptions struct {
filterStatus string filterStatus string
filterSize string filterSize string
filterReflect string filterRegexp string
filterRegex string
filterWords string filterWords string
matcherStatus string matcherStatus string
matcherSize string matcherSize string
matcherReflect string matcherRegexp string
matcherRegex string
matcherWords string matcherWords string
headers headerFlags headers headerFlags
} }
@ -52,19 +50,17 @@ func main() {
flag.BoolVar(&conf.TLSSkipVerify, "k", false, "Skip TLS identity verification (insecure)") 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.filterStatus, "fc", "", "Filter HTTP status codes from response")
flag.StringVar(&opts.filterSize, "fs", "", "Filter HTTP response size") 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(&opts.filterWords, "fw", "", "Filter by amount of words in response")
flag.StringVar(&conf.Data, "d", "", "POST data.") flag.StringVar(&conf.Data, "d", "", "POST data.")
flag.BoolVar(&conf.Colors, "c", false, "Colorize output.") 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.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.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.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.StringVar(&conf.Method, "X", "GET", "HTTP method to use.")
flag.BoolVar(&conf.Quiet, "s", false, "Do not print additional information (silent mode)") flag.BoolVar(&conf.Quiet, "s", false, "Do not print additional information (silent mode)")
flag.IntVar(&conf.Threads, "t", 20, "Number of concurrent threads.") flag.IntVar(&conf.Threads, "t", 20, "Number of concurrent threads.")
//flag.StringVar(&opts.matcherReflect, "mref", "", "Match reflected payload")
flag.Parse() flag.Parse()
if err := prepareConfig(&opts, &conf); err != nil { if err := prepareConfig(&opts, &conf); err != nil {
fmt.Fprintf(os.Stderr, "Encountered error(s): %s\n", err) 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) 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 parseOpts.filterWords != "" {
if err := addFilter(conf, "word", parseOpts.filterWords); err != nil { if err := addFilter(conf, "word", parseOpts.filterWords); err != nil {
errlist = multierror.Append(errlist, err) errlist = multierror.Append(errlist, err)
@ -179,6 +180,11 @@ func prepareFilters(parseOpts *cliOptions, conf *ffuf.Config) error {
errlist = multierror.Append(errlist, err) 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 parseOpts.matcherWords != "" {
if err := addMatcher(conf, "word", parseOpts.matcherWords); err != nil { if err := addMatcher(conf, "word", parseOpts.matcherWords); err != nil {
errlist = multierror.Append(errlist, err) errlist = multierror.Append(errlist, err)

View File

@ -16,5 +16,8 @@ func NewFilterByName(name string, value string) (ffuf.FilterProvider, error) {
if name == "word" { if name == "word" {
return NewWordFilter(value) return NewWordFilter(value)
} }
if name == "regexp" {
return NewRegexpFilter(value)
}
return nil, fmt.Errorf("Could not create filter with name %s", name) return nil, fmt.Errorf("Could not create filter with name %s", name)
} }

29
pkg/filter/regex.go Normal file
View File

@ -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)
}