Add word filter / matcher
This commit is contained in:
parent
a1986d176a
commit
fbafd82c62
14
main.go
14
main.go
@ -21,10 +21,12 @@ type cliOptions struct {
|
|||||||
filterSize string
|
filterSize string
|
||||||
filterReflect string
|
filterReflect string
|
||||||
filterRegex string
|
filterRegex string
|
||||||
|
filterWords string
|
||||||
matcherStatus string
|
matcherStatus string
|
||||||
matcherSize string
|
matcherSize string
|
||||||
matcherReflect string
|
matcherReflect string
|
||||||
matcherRegex string
|
matcherRegex string
|
||||||
|
matcherWords string
|
||||||
headers headerFlags
|
headers headerFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,12 +52,14 @@ 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.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.filterRegex, "fr", "", "Filter regex")
|
||||||
//flag.StringVar(&opts.filterReflect, "fref", "", "Filter reflected payload")
|
//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.matcherWords, "mw", "", "Match amount of words in response")
|
||||||
//flag.StringVar(&opts.matcherRegex, "mr", "", "Match regex")
|
//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)")
|
||||||
@ -160,6 +164,11 @@ func prepareFilters(parseOpts *cliOptions, conf *ffuf.Config) error {
|
|||||||
errlist = multierror.Append(errlist, err)
|
errlist = multierror.Append(errlist, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if parseOpts.filterWords != "" {
|
||||||
|
if err := addFilter(conf, "word", parseOpts.filterWords); err != nil {
|
||||||
|
errlist = multierror.Append(errlist, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if parseOpts.matcherStatus != "" {
|
if parseOpts.matcherStatus != "" {
|
||||||
if err := addMatcher(conf, "status", parseOpts.matcherStatus); err != nil {
|
if err := addMatcher(conf, "status", parseOpts.matcherStatus); err != nil {
|
||||||
errlist = multierror.Append(errlist, err)
|
errlist = multierror.Append(errlist, err)
|
||||||
@ -170,6 +179,11 @@ func prepareFilters(parseOpts *cliOptions, conf *ffuf.Config) error {
|
|||||||
errlist = multierror.Append(errlist, err)
|
errlist = multierror.Append(errlist, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if parseOpts.matcherWords != "" {
|
||||||
|
if err := addMatcher(conf, "word", parseOpts.matcherWords); err != nil {
|
||||||
|
errlist = multierror.Append(errlist, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
return errlist.ErrorOrNil()
|
return errlist.ErrorOrNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ type Response struct {
|
|||||||
Headers map[string][]string
|
Headers map[string][]string
|
||||||
Data []byte
|
Data []byte
|
||||||
ContentLength int64
|
ContentLength int64
|
||||||
|
ContentWords int64
|
||||||
Cancelled bool
|
Cancelled bool
|
||||||
Request *Request
|
Request *Request
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package filter
|
package filter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ffuf/ffuf/pkg/ffuf"
|
"github.com/ffuf/ffuf/pkg/ffuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -11,5 +13,8 @@ func NewFilterByName(name string, value string) (ffuf.FilterProvider, error) {
|
|||||||
if name == "size" {
|
if name == "size" {
|
||||||
return NewSizeFilter(value)
|
return NewSizeFilter(value)
|
||||||
}
|
}
|
||||||
return nil, nil
|
if name == "word" {
|
||||||
|
return NewWordFilter(value)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Could not create filter with name %s", name)
|
||||||
}
|
}
|
||||||
|
|||||||
43
pkg/filter/words.go
Normal file
43
pkg/filter/words.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package filter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ffuf/ffuf/pkg/ffuf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WordFilter struct {
|
||||||
|
Value []int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWordFilter(value string) (ffuf.FilterProvider, error) {
|
||||||
|
var intvals []int64
|
||||||
|
for _, sv := range strings.Split(value, ",") {
|
||||||
|
intval, err := strconv.ParseInt(sv, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return &WordFilter{}, fmt.Errorf("Word filter or matcher (-fw / -mw): invalid value: %s", value)
|
||||||
|
}
|
||||||
|
intvals = append(intvals, intval)
|
||||||
|
}
|
||||||
|
return &WordFilter{Value: intvals}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *WordFilter) Filter(response *ffuf.Response) (bool, error) {
|
||||||
|
wordsSize := len(strings.Split(string(response.Data), " "))
|
||||||
|
for _, iv := range f.Value {
|
||||||
|
if iv == int64(wordsSize) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *WordFilter) Repr() string {
|
||||||
|
var strval []string
|
||||||
|
for _, iv := range f.Value {
|
||||||
|
strval = append(strval, strconv.Itoa(int(iv)))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Response words: %s", strings.Join(strval, ","))
|
||||||
|
}
|
||||||
@ -98,7 +98,7 @@ func (s *Stdoutput) resultQuiet(resp ffuf.Response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stdoutput) resultNormal(resp ffuf.Response) {
|
func (s *Stdoutput) resultNormal(resp ffuf.Response) {
|
||||||
res_str := fmt.Sprintf("%s%-23s [Status: %s, Size: %d]", TERMINAL_CLEAR_LINE, resp.Request.Input, s.colorizeStatus(resp.StatusCode), resp.ContentLength)
|
res_str := fmt.Sprintf("%s%-23s [Status: %s, Size: %d, Words: %d]", TERMINAL_CLEAR_LINE, resp.Request.Input, s.colorizeStatus(resp.StatusCode), resp.ContentLength, resp.ContentWords)
|
||||||
fmt.Println(res_str)
|
fmt.Println(res_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,5 +94,8 @@ func (r *SimpleRunner) Execute(req *ffuf.Request) (ffuf.Response, error) {
|
|||||||
resp.Data = respbody
|
resp.Data = respbody
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wordsSize := len(strings.Split(string(resp.Data), " "))
|
||||||
|
resp.ContentWords = int64(wordsSize)
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user