diff --git a/README.md b/README.md index 56f4b38..42d3581 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ \/_/ \/_/ \/___/ \/_/ ``` - # ffuf - Fuzz Faster U Fool A fast web fuzzer written in Go. @@ -172,53 +171,58 @@ eg. `ffuf -u https://example.org/FUZZ -w /path/to/wordlist` ## Installation - - [Download](https://github.com/ffuf/ffuf/releases/latest) a prebuilt binary from [releases page](https://github.com/ffuf/ffuf/releases/latest), unpack and run! - or - - If you have go compiler installed: `go get github.com/ffuf/ffuf` +- [Download](https://github.com/ffuf/ffuf/releases/latest) a prebuilt binary from [releases page](https://github.com/ffuf/ffuf/releases/latest), unpack and run! + or +- If you have go compiler installed: `go get github.com/ffuf/ffuf` The only dependency of ffuf is Go 1.11. No dependencies outside of Go standard library are needed. ## Changelog - master - - New - - Changed - - New CLI flag: -i, dummy flag that does nothing. for compatibility with copy as curl. - - New CLI flag: -b/--cookie, cookie data for compatibility with copy as curl. - - Filtering and matching by status code, response size or word count now allow using ranges in addition to single values + + - New + - New CLI flag: -l, shows target location of redirect responses + - Changed + - New CLI flag: -i, dummy flag that does nothing. for compatibility with copy as curl. + - New CLI flag: -b/--cookie, cookie data for compatibility with copy as curl. + - Filtering and matching by status code, response size or word count now allow using ranges in addition to single values - v0.10 - - New - - New CLI flag: -ac to autocalibrate response size and word filters based on few preset URLs. - - New CLI flag: -timeout to specify custom timeouts for all HTTP requests. - - New CLI flag: --data for compatibility with copy as curl functionality of browsers. - - New CLI flag: --compressed, dummy flag that does nothing. for compatibility with copy as curl. - - New CLI flags: --input-cmd, and --input-num to handle input generation using external commands. Mutators for example. Environment variable FFUF_NUM will be updated on every call of the command. - - When --input-cmd is used, display position instead of the payload in results. The output file (of all formats) will include the payload in addition to the position however. - - Changed - - Wordlist can also be read from standard input - - Defining -d or --data implies POST method if -X doesn't set it to something else than GET + - New + + - New CLI flag: -ac to autocalibrate response size and word filters based on few preset URLs. + - New CLI flag: -timeout to specify custom timeouts for all HTTP requests. + - New CLI flag: --data for compatibility with copy as curl functionality of browsers. + - New CLI flag: --compressed, dummy flag that does nothing. for compatibility with copy as curl. + - New CLI flags: --input-cmd, and --input-num to handle input generation using external commands. Mutators for example. Environment variable FFUF_NUM will be updated on every call of the command. + - When --input-cmd is used, display position instead of the payload in results. The output file (of all formats) will include the payload in addition to the position however. + + - Changed + - Wordlist can also be read from standard input + - Defining -d or --data implies POST method if -X doesn't set it to something else than GET - v0.9 - - New - - New output file formats: CSV and eCSV (CSV with base64 encoded input field to avoid CSV breakage with payloads containing a comma) - - New CLI flag to follow redirects - - Erroring connections will be retried once - - Error counter in status bar - - New CLI flags: -se (stop on spurious errors) and -sa (stop on all errors, implies -se and -sf) - - New CLI flags: -e to provide a list of extensions to add to wordlist entries, and -D to provide DirSearch wordlist format compatibility. - - Wildcard option for response status code matcher. + - New + - New output file formats: CSV and eCSV (CSV with base64 encoded input field to avoid CSV breakage with payloads containing a comma) + - New CLI flag to follow redirects + - Erroring connections will be retried once + - Error counter in status bar + - New CLI flags: -se (stop on spurious errors) and -sa (stop on all errors, implies -se and -sf) + - New CLI flags: -e to provide a list of extensions to add to wordlist entries, and -D to provide DirSearch wordlist format compatibility. + - Wildcard option for response status code matcher. - v0.8 - - New - - New CLI flag to write output to a file in JSON format - - New CLI flag to stop on spurious 403 responses - - Changed - - Regex matching / filtering now matches the headers alongside of the response body + - New + - New CLI flag to write output to a file in JSON format + - New CLI flag to stop on spurious 403 responses + - Changed + - Regex matching / filtering now matches the headers alongside of the response body ## TODO - - Tests! - - Optional scope for redirects - - Client / server architecture to queue jobs and fetch the results later - - Fuzzing multiple values at the same time - - Output module to push the results to an HTTP API + +- Tests! +- Optional scope for redirects +- Client / server architecture to queue jobs and fetch the results later +- Fuzzing multiple values at the same time +- Output module to push the results to an HTTP API diff --git a/main.go b/main.go index 67b1317..d01491f 100644 --- a/main.go +++ b/main.go @@ -82,6 +82,7 @@ func main() { flag.StringVar(&conf.Method, "X", "GET", "HTTP method to use") flag.StringVar(&conf.OutputFile, "o", "", "Write output to file") flag.StringVar(&opts.outputFormat, "of", "json", "Output file format. Available formats: json, csv, ecsv") + flag.BoolVar(&conf.ShowRedirectLocation, "l", false, "Show target location of redirect responses") flag.BoolVar(&conf.Quiet, "s", false, "Do not print additional information (silent mode)") flag.BoolVar(&conf.StopOn403, "sf", false, "Stop when > 95% of responses return 403 Forbidden") flag.BoolVar(&conf.StopOnErrors, "se", false, "Stop on spurious errors") diff --git a/pkg/ffuf/config.go b/pkg/ffuf/config.go index 7a9409b..b978709 100644 --- a/pkg/ffuf/config.go +++ b/pkg/ffuf/config.go @@ -16,35 +16,36 @@ type optRange struct { } type Config struct { - StaticHeaders map[string]string - FuzzHeaders map[string]string - Extensions []string - DirSearchCompat bool - Method string - Url string - TLSVerify bool - Data string - Quiet bool - Colors bool - Wordlist string - InputCommand string - InputNum int - OutputFile string - OutputFormat string - StopOn403 bool - StopOnErrors bool - StopOnAll bool - FollowRedirects bool - AutoCalibration bool - Timeout int - ProgressFrequency int - Delay optRange - Filters []FilterProvider - Matchers []FilterProvider - Threads int - Context context.Context - ProxyURL func(*http.Request) (*url.URL, error) - CommandLine string + StaticHeaders map[string]string + FuzzHeaders map[string]string + Extensions []string + DirSearchCompat bool + Method string + Url string + TLSVerify bool + Data string + Quiet bool + Colors bool + Wordlist string + InputCommand string + InputNum int + OutputFile string + OutputFormat string + StopOn403 bool + StopOnErrors bool + StopOnAll bool + FollowRedirects bool + AutoCalibration bool + ShowRedirectLocation bool + Timeout int + ProgressFrequency int + Delay optRange + Filters []FilterProvider + Matchers []FilterProvider + Threads int + Context context.Context + ProxyURL func(*http.Request) (*url.URL, error) + CommandLine string } func NewConfig(ctx context.Context) Config { @@ -60,6 +61,7 @@ func NewConfig(ctx context.Context) Config { conf.StopOn403 = false conf.StopOnErrors = false conf.StopOnAll = false + conf.ShowRedirectLocation = false conf.FollowRedirects = false conf.InputCommand = "" conf.InputNum = 0 diff --git a/pkg/ffuf/response.go b/pkg/ffuf/response.go index c67b7ba..995cc93 100644 --- a/pkg/ffuf/response.go +++ b/pkg/ffuf/response.go @@ -15,6 +15,17 @@ type Response struct { Request *Request } +// GetRedirectLocation returns the redirect location for a 3xx redirect HTTP response +func (resp *Response) GetRedirectLocation() string { + + redirectLocation := "" + if resp.StatusCode >= 300 && resp.StatusCode <= 399 { + redirectLocation = resp.Headers["Location"][0] + } + + return redirectLocation +} + func NewResponse(httpresp *http.Response, req *Request) Response { var resp Response resp.Request = req diff --git a/pkg/output/stdout.go b/pkg/output/stdout.go index d91a2f0..c51597e 100644 --- a/pkg/output/stdout.go +++ b/pkg/output/stdout.go @@ -156,14 +156,25 @@ func (s *Stdoutput) resultQuiet(resp ffuf.Response) { } func (s *Stdoutput) resultNormal(resp ffuf.Response) { - var res_str string + var responseString string if len(s.config.InputCommand) > 0 { // If we're using external command for input, display the position instead of input - res_str = fmt.Sprintf("%s%-23s [Status: %s, Size: %d, Words: %d]", TERMINAL_CLEAR_LINE, strconv.Itoa(resp.Request.Position), s.colorizeStatus(resp.StatusCode), resp.ContentLength, resp.ContentWords) + responseString = fmt.Sprintf("%s%-23s [Status: %s, Size: %d, Words: %d%s]", TERMINAL_CLEAR_LINE, strconv.Itoa(resp.Request.Position), s.colorizeStatus(resp.StatusCode), resp.ContentLength, resp.ContentWords, s.addRedirectLocation(resp)) } else { - 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) + responseString = fmt.Sprintf("%s%-23s [Status: %s, Size: %d, Words: %d%s]", TERMINAL_CLEAR_LINE, resp.Request.Input, s.colorizeStatus(resp.StatusCode), resp.ContentLength, resp.ContentWords, s.addRedirectLocation(resp)) } - fmt.Println(res_str) + fmt.Println(responseString) +} + +// addRedirectLocation returns a formatted string containing the Redirect location or returns an empty string +func (s *Stdoutput) addRedirectLocation(resp ffuf.Response) string { + if s.config.ShowRedirectLocation == true { + redirectLocation := resp.GetRedirectLocation() + if redirectLocation != "" { + return fmt.Sprintf(", ->: %s", redirectLocation) + } + } + return "" } func (s *Stdoutput) colorizeStatus(status int64) string {