mirror of
https://github.com/ffuf/ffuf
synced 2025-03-01 21:37:13 +00:00
Implement -v (verbose) flag (#100)
This commit is contained in:
parent
ad927ef939
commit
3949e49b3b
4 changed files with 17 additions and 19 deletions
|
@ -139,7 +139,6 @@ Usage of ./ffuf:
|
||||||
-input-num int
|
-input-num int
|
||||||
Number of inputs to test. Used in conjunction with --input-cmd. (default 100)
|
Number of inputs to test. Used in conjunction with --input-cmd. (default 100)
|
||||||
-k TLS identity verification
|
-k TLS identity verification
|
||||||
-l Show target location of redirect responses
|
|
||||||
-mc string
|
-mc string
|
||||||
Match HTTP status codes from respose, use "all" to match every response code. (default "200,204,301,302,307,401,403")
|
Match HTTP status codes from respose, use "all" to match every response code. (default "200,204,301,302,307,401,403")
|
||||||
-ml string
|
-ml string
|
||||||
|
@ -172,6 +171,7 @@ Usage of ./ffuf:
|
||||||
HTTP request timeout in seconds. (default 10)
|
HTTP request timeout in seconds. (default 10)
|
||||||
-u string
|
-u string
|
||||||
Target URL
|
Target URL
|
||||||
|
-v Verbose output, printing full URL and redirect location (if any) with the results.
|
||||||
-w value
|
-w value
|
||||||
Wordlist file path and (optional) custom fuzz keyword, using colon as delimiter. Use file path '-' to read from standard input. Can be supplied multiple times. Format: '/path/to/wordlist:KEYWORD'
|
Wordlist file path and (optional) custom fuzz keyword, using colon as delimiter. Use file path '-' to read from standard input. Can be supplied multiple times. Format: '/path/to/wordlist:KEYWORD'
|
||||||
-x string
|
-x string
|
||||||
|
@ -197,10 +197,12 @@ The only dependency of ffuf is Go 1.11. No dependencies outside of Go standard l
|
||||||
- Redirect location is always shown in the output files (when using `-o`)
|
- Redirect location is always shown in the output files (when using `-o`)
|
||||||
- Full URL is always shown in the output files (when using `-o`)
|
- Full URL is always shown in the output files (when using `-o`)
|
||||||
- HTML output format got [DataTables](https://datatables.net/) support allowing realtime searches, sorting by column etc.
|
- HTML output format got [DataTables](https://datatables.net/) support allowing realtime searches, sorting by column etc.
|
||||||
|
- New CLI flag `-v` for verbose output. Including full URL, and redirect location.
|
||||||
- Changed
|
- Changed
|
||||||
- Fixed a bug in the default multi wordlist mode
|
- Fixed a bug in the default multi wordlist mode
|
||||||
- Fixed JSON output regression, where all the input data was always encoded in base64
|
- Fixed JSON output regression, where all the input data was always encoded in base64
|
||||||
- `--debug-log` no correctly logs connection errors
|
- `--debug-log` no correctly logs connection errors
|
||||||
|
- Removed `-l` flag in favor of `-v`
|
||||||
|
|
||||||
- v0.11
|
- v0.11
|
||||||
|
|
||||||
|
|
2
main.go
2
main.go
|
@ -93,7 +93,6 @@ func main() {
|
||||||
flag.StringVar(&conf.Method, "X", "GET", "HTTP method to use")
|
flag.StringVar(&conf.Method, "X", "GET", "HTTP method to use")
|
||||||
flag.StringVar(&conf.OutputFile, "o", "", "Write output to file")
|
flag.StringVar(&conf.OutputFile, "o", "", "Write output to file")
|
||||||
flag.StringVar(&opts.outputFormat, "of", "json", "Output file format. Available formats: json, ejson, html, md, csv, ecsv")
|
flag.StringVar(&opts.outputFormat, "of", "json", "Output file format. Available formats: json, ejson, html, md, 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.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.StopOn403, "sf", false, "Stop when > 95% of responses return 403 Forbidden")
|
||||||
flag.BoolVar(&conf.StopOnErrors, "se", false, "Stop on spurious errors")
|
flag.BoolVar(&conf.StopOnErrors, "se", false, "Stop on spurious errors")
|
||||||
|
@ -103,6 +102,7 @@ func main() {
|
||||||
flag.Var(&opts.AutoCalibrationStrings, "acc", "Custom auto-calibration string. Can be used multiple times. Implies -ac")
|
flag.Var(&opts.AutoCalibrationStrings, "acc", "Custom auto-calibration string. Can be used multiple times. Implies -ac")
|
||||||
flag.IntVar(&conf.Threads, "t", 40, "Number of concurrent threads.")
|
flag.IntVar(&conf.Threads, "t", 40, "Number of concurrent threads.")
|
||||||
flag.IntVar(&conf.Timeout, "timeout", 10, "HTTP request timeout in seconds.")
|
flag.IntVar(&conf.Timeout, "timeout", 10, "HTTP request timeout in seconds.")
|
||||||
|
flag.BoolVar(&conf.Verbose, "v", false, "Verbose output, printing full URL and redirect location (if any) with the results.")
|
||||||
flag.BoolVar(&opts.showVersion, "V", false, "Show version information.")
|
flag.BoolVar(&opts.showVersion, "V", false, "Show version information.")
|
||||||
flag.StringVar(&opts.debugLog, "debug-log", "", "Write all of the internal logging to the specified file.")
|
flag.StringVar(&opts.debugLog, "debug-log", "", "Write all of the internal logging to the specified file.")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
|
@ -37,7 +37,6 @@ type Config struct {
|
||||||
FollowRedirects bool
|
FollowRedirects bool
|
||||||
AutoCalibration bool
|
AutoCalibration bool
|
||||||
AutoCalibrationStrings []string
|
AutoCalibrationStrings []string
|
||||||
ShowRedirectLocation bool
|
|
||||||
Timeout int
|
Timeout int
|
||||||
ProgressFrequency int
|
ProgressFrequency int
|
||||||
Delay optRange
|
Delay optRange
|
||||||
|
@ -47,6 +46,7 @@ type Config struct {
|
||||||
Context context.Context
|
Context context.Context
|
||||||
ProxyURL func(*http.Request) (*url.URL, error)
|
ProxyURL func(*http.Request) (*url.URL, error)
|
||||||
CommandLine string
|
CommandLine string
|
||||||
|
Verbose bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type InputProviderConfig struct {
|
type InputProviderConfig struct {
|
||||||
|
@ -67,7 +67,6 @@ func NewConfig(ctx context.Context) Config {
|
||||||
conf.StopOn403 = false
|
conf.StopOn403 = false
|
||||||
conf.StopOnErrors = false
|
conf.StopOnErrors = false
|
||||||
conf.StopOnAll = false
|
conf.StopOnAll = false
|
||||||
conf.ShowRedirectLocation = false
|
|
||||||
conf.FollowRedirects = false
|
conf.FollowRedirects = false
|
||||||
conf.InputProviders = make([]InputProviderConfig, 0)
|
conf.InputProviders = make([]InputProviderConfig, 0)
|
||||||
conf.CommandKeywords = make([]string, 0)
|
conf.CommandKeywords = make([]string, 0)
|
||||||
|
@ -81,5 +80,6 @@ func NewConfig(ctx context.Context) Config {
|
||||||
// Progress update frequency, in milliseconds
|
// Progress update frequency, in milliseconds
|
||||||
conf.ProgressFrequency = 100
|
conf.ProgressFrequency = 100
|
||||||
conf.DirSearchCompat = false
|
conf.DirSearchCompat = false
|
||||||
|
conf.Verbose = false
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ func (s *Stdoutput) printResult(resp ffuf.Response) {
|
||||||
if s.config.Quiet {
|
if s.config.Quiet {
|
||||||
s.resultQuiet(resp)
|
s.resultQuiet(resp)
|
||||||
} else {
|
} else {
|
||||||
if len(resp.Request.Input) > 1 {
|
if len(resp.Request.Input) > 1 || s.config.Verbose {
|
||||||
// Print a multi-line result (when using multiple input keywords and wordlists)
|
// Print a multi-line result (when using multiple input keywords and wordlists)
|
||||||
s.resultMultiline(resp)
|
s.resultMultiline(resp)
|
||||||
} else {
|
} else {
|
||||||
|
@ -199,9 +199,16 @@ func (s *Stdoutput) resultQuiet(resp ffuf.Response) {
|
||||||
func (s *Stdoutput) resultMultiline(resp ffuf.Response) {
|
func (s *Stdoutput) resultMultiline(resp ffuf.Response) {
|
||||||
var res_hdr, res_str string
|
var res_hdr, res_str string
|
||||||
res_str = "%s%s * %s: %s\n"
|
res_str = "%s%s * %s: %s\n"
|
||||||
res_hdr = fmt.Sprintf("%s[Status: %d, Size: %d, Words: %d, Lines: %d%s]", TERMINAL_CLEAR_LINE, resp.StatusCode, resp.ContentLength, resp.ContentWords, resp.ContentLines, s.addRedirectLocation(resp))
|
res_hdr = fmt.Sprintf("%s[Status: %d, Size: %d, Words: %d, Lines: %d]", TERMINAL_CLEAR_LINE, resp.StatusCode, resp.ContentLength, resp.ContentWords, resp.ContentLines)
|
||||||
res_hdr = s.colorize(res_hdr, resp.StatusCode)
|
res_hdr = s.colorize(res_hdr, resp.StatusCode)
|
||||||
reslines := ""
|
reslines := ""
|
||||||
|
if s.config.Verbose {
|
||||||
|
reslines = fmt.Sprintf("%s%s| URL | %s\n", reslines, TERMINAL_CLEAR_LINE, resp.Request.Url)
|
||||||
|
redirectLocation := resp.GetRedirectLocation()
|
||||||
|
if redirectLocation != "" {
|
||||||
|
reslines = fmt.Sprintf("%s%s| --> | %s\n", reslines, TERMINAL_CLEAR_LINE, redirectLocation)
|
||||||
|
}
|
||||||
|
}
|
||||||
for k, v := range resp.Request.Input {
|
for k, v := range resp.Request.Input {
|
||||||
if inSlice(k, s.config.CommandKeywords) {
|
if inSlice(k, s.config.CommandKeywords) {
|
||||||
// If we're using external command for input, display the position instead of input
|
// If we're using external command for input, display the position instead of input
|
||||||
|
@ -211,26 +218,15 @@ func (s *Stdoutput) resultMultiline(resp ffuf.Response) {
|
||||||
reslines = fmt.Sprintf(res_str, reslines, TERMINAL_CLEAR_LINE, k, v)
|
reslines = fmt.Sprintf(res_str, reslines, TERMINAL_CLEAR_LINE, k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Printf("%s\n%s", res_hdr, reslines)
|
fmt.Printf("%s\n%s\n", res_hdr, reslines)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stdoutput) resultNormal(resp ffuf.Response) {
|
func (s *Stdoutput) resultNormal(resp ffuf.Response) {
|
||||||
var res_str string
|
var res_str string
|
||||||
res_str = fmt.Sprintf("%s%-23s [Status: %s, Size: %d, Words: %d, Lines: %d%s]", TERMINAL_CLEAR_LINE, s.prepareInputsOneLine(resp), s.colorize(fmt.Sprintf("%d", resp.StatusCode), resp.StatusCode), resp.ContentLength, resp.ContentWords, resp.ContentLines, s.addRedirectLocation(resp))
|
res_str = fmt.Sprintf("%s%-23s [Status: %s, Size: %d, Words: %d, Lines: %d]", TERMINAL_CLEAR_LINE, s.prepareInputsOneLine(resp), s.colorize(fmt.Sprintf("%d", resp.StatusCode), resp.StatusCode), resp.ContentLength, resp.ContentWords, resp.ContentLines)
|
||||||
fmt.Println(res_str)
|
fmt.Println(res_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) colorize(input string, status int64) string {
|
func (s *Stdoutput) colorize(input string, status int64) string {
|
||||||
if !s.config.Colors {
|
if !s.config.Colors {
|
||||||
return fmt.Sprintf("%s", input)
|
return fmt.Sprintf("%s", input)
|
||||||
|
|
Loading…
Add table
Reference in a new issue