From 582aa0083315daf08af601a114b96221b2324ccc Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Mon, 21 Jan 2019 22:43:04 +0200 Subject: [PATCH] Added proxy functionality --- README.md | 2 ++ main.go | 16 +++++++++++++++- pkg/ffuf/config.go | 4 ++++ pkg/runner/simple.go | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d95a2ad..a14c288 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,8 @@ To define the test case for ffuf, use the keyword `FUZZ` anywhere in the URL (`- Target URL -w string Wordlist path + -x string + HTTP Proxy URL ``` eg. `ffuf -u https://example.org/FUZZ -w /path/to/wordlist` diff --git a/main.go b/main.go index ae4bb12..c531a4f 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,8 @@ import ( "context" "flag" "fmt" + "net/http" + "net/url" "os" "strconv" "strings" @@ -25,6 +27,7 @@ type cliOptions struct { matcherSize string matcherRegexp string matcherWords string + proxyURL string headers multiStringFlag showVersion bool } @@ -60,7 +63,8 @@ func main() { 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(&conf.Method, "X", "GET", "HTTP method to use.") + flag.StringVar(&opts.proxyURL, "x", "", "HTTP Proxy URL") + 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", 40, "Number of concurrent threads.") flag.BoolVar(&opts.showVersion, "V", false, "Show version information.") @@ -165,6 +169,16 @@ func prepareConfig(parseOpts *cliOptions, conf *ffuf.Config) error { } } + // Verify proxy url format + if len(parseOpts.proxyURL) > 0 { + pu, err := url.Parse(parseOpts.proxyURL) + if err != nil { + errs.Add(fmt.Errorf("Bad proxy url (-x) format: %s", err)) + } else { + conf.ProxyURL = http.ProxyURL(pu) + } + } + //Search for keyword from URL and POST data too if strings.Index(conf.Url, "FUZZ") != -1 { foundkeyword = true diff --git a/pkg/ffuf/config.go b/pkg/ffuf/config.go index 8f52f29..a689b35 100644 --- a/pkg/ffuf/config.go +++ b/pkg/ffuf/config.go @@ -2,6 +2,8 @@ package ffuf import ( "context" + "net/http" + "net/url" ) //optRange stores either a single float, in which case the value is stored in min and IsRange is false, @@ -28,6 +30,7 @@ type Config struct { Matchers []FilterProvider Threads int Context context.Context + ProxyURL func(*http.Request) (*url.URL, error) } func NewConfig(ctx context.Context) Config { @@ -40,6 +43,7 @@ func NewConfig(ctx context.Context) Config { conf.TLSSkipVerify = false conf.Data = "" conf.Quiet = false + conf.ProxyURL = http.ProxyFromEnvironment conf.Filters = make([]FilterProvider, 0) conf.Delay = optRange{0, 0, false, false} return conf diff --git a/pkg/runner/simple.go b/pkg/runner/simple.go index e5ab5ee..2898f3a 100644 --- a/pkg/runner/simple.go +++ b/pkg/runner/simple.go @@ -30,6 +30,7 @@ func NewSimpleRunner(conf *ffuf.Config) ffuf.RunnerProvider { CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, Timeout: time.Duration(10 * time.Second), Transport: &http.Transport{ + Proxy: conf.ProxyURL, MaxIdleConns: 1000, MaxIdleConnsPerHost: 500, MaxConnsPerHost: 500,