2018-11-08 09:26:32 +00:00
package main
import (
"context"
"flag"
"fmt"
2023-02-04 11:23:31 +00:00
"io"
"log"
"os"
"strings"
"time"
2018-11-08 09:26:32 +00:00
"github.com/ffuf/ffuf/pkg/ffuf"
2023-02-02 09:51:11 +00:00
"github.com/ffuf/ffuf/pkg/filter"
2018-11-08 09:26:32 +00:00
"github.com/ffuf/ffuf/pkg/input"
2021-04-18 09:54:17 +00:00
"github.com/ffuf/ffuf/pkg/interactive"
2018-11-08 09:26:32 +00:00
"github.com/ffuf/ffuf/pkg/output"
"github.com/ffuf/ffuf/pkg/runner"
2023-02-04 11:23:31 +00:00
"github.com/ffuf/ffuf/pkg/scraper"
2018-11-08 09:26:32 +00:00
)
2018-12-05 22:57:42 +00:00
type multiStringFlag [ ] string
2020-09-16 08:08:09 +00:00
type wordlistFlag [ ] string
2018-11-08 09:26:32 +00:00
2018-12-05 22:57:42 +00:00
func ( m * multiStringFlag ) String ( ) string {
2018-11-08 09:26:32 +00:00
return ""
}
2020-09-16 08:08:09 +00:00
func ( m * wordlistFlag ) String ( ) string {
return ""
}
2018-12-05 22:57:42 +00:00
func ( m * multiStringFlag ) Set ( value string ) error {
2020-09-16 08:08:09 +00:00
* m = append ( * m , value )
return nil
}
func ( m * wordlistFlag ) Set ( value string ) error {
2020-09-14 20:13:21 +00:00
delimited := strings . Split ( value , "," )
if len ( delimited ) > 1 {
* m = append ( * m , delimited ... )
} else {
* m = append ( * m , value )
}
2018-11-08 09:26:32 +00:00
return nil
}
2023-02-02 09:51:11 +00:00
// ParseFlags parses the command line flags and (re)populates the ConfigOptions struct
2020-09-27 16:24:06 +00:00
func ParseFlags ( opts * ffuf . ConfigOptions ) * ffuf . ConfigOptions {
2019-06-04 21:26:27 +00:00
var ignored bool
2020-09-27 16:24:06 +00:00
var cookies , autocalibrationstrings , headers , inputcommands multiStringFlag
var wordlists wordlistFlag
cookies = opts . HTTP . Cookies
autocalibrationstrings = opts . General . AutoCalibrationStrings
headers = opts . HTTP . Headers
inputcommands = opts . Input . Inputcommands
2022-01-22 17:50:57 +00:00
wordlists = opts . Input . Wordlists
2020-09-27 16:24:06 +00:00
2019-06-04 21:26:27 +00:00
flag . BoolVar ( & ignored , "compressed" , true , "Dummy flag for copy as curl functionality (ignored)" )
2019-06-26 19:44:52 +00:00
flag . BoolVar ( & ignored , "i" , true , "Dummy flag for copy as curl functionality (ignored)" )
2020-09-27 16:24:06 +00:00
flag . BoolVar ( & ignored , "k" , false , "Dummy flag for backwards compatibility" )
2021-05-13 16:07:00 +00:00
flag . BoolVar ( & opts . Output . OutputSkipEmptyFile , "or" , opts . Output . OutputSkipEmptyFile , "Don't create the output file if we don't have results" )
2020-09-27 16:24:06 +00:00
flag . BoolVar ( & opts . General . AutoCalibration , "ac" , opts . General . AutoCalibration , "Automatically calibrate filtering options" )
2022-03-20 17:13:32 +00:00
flag . BoolVar ( & opts . General . AutoCalibrationPerHost , "ach" , opts . General . AutoCalibration , "Per host autocalibration" )
2020-09-27 16:24:06 +00:00
flag . BoolVar ( & opts . General . Colors , "c" , opts . General . Colors , "Colorize output." )
2022-03-06 14:39:33 +00:00
flag . BoolVar ( & opts . General . Json , "json" , opts . General . Json , "JSON output, printing newline-delimited JSON records" )
2021-04-26 20:04:12 +00:00
flag . BoolVar ( & opts . General . Noninteractive , "noninteractive" , opts . General . Noninteractive , "Disable the interactive console functionality" )
2020-09-27 16:24:06 +00:00
flag . BoolVar ( & opts . General . Quiet , "s" , opts . General . Quiet , "Do not print additional information (silent mode)" )
flag . BoolVar ( & opts . General . ShowVersion , "V" , opts . General . ShowVersion , "Show version information." )
flag . BoolVar ( & opts . General . StopOn403 , "sf" , opts . General . StopOn403 , "Stop when > 95% of responses return 403 Forbidden" )
flag . BoolVar ( & opts . General . StopOnAll , "sa" , opts . General . StopOnAll , "Stop on all error cases. Implies -sf and -se." )
flag . BoolVar ( & opts . General . StopOnErrors , "se" , opts . General . StopOnErrors , "Stop on spurious errors" )
flag . BoolVar ( & opts . General . Verbose , "v" , opts . General . Verbose , "Verbose output, printing full URL and redirect location (if any) with the results." )
flag . BoolVar ( & opts . HTTP . FollowRedirects , "r" , opts . HTTP . FollowRedirects , "Follow redirects" )
flag . BoolVar ( & opts . HTTP . IgnoreBody , "ignore-body" , opts . HTTP . IgnoreBody , "Do not fetch the response content." )
flag . BoolVar ( & opts . HTTP . Recursion , "recursion" , opts . HTTP . Recursion , "Scan recursively. Only FUZZ keyword is supported, and URL (-u) has to end in it." )
2022-01-28 15:49:53 +00:00
flag . BoolVar ( & opts . HTTP . Http2 , "http2" , opts . HTTP . Http2 , "Use HTTP2 protocol" )
2020-09-27 16:24:06 +00:00
flag . BoolVar ( & opts . Input . DirSearchCompat , "D" , opts . Input . DirSearchCompat , "DirSearch wordlist compatibility mode. Used in conjunction with -e flag." )
flag . BoolVar ( & opts . Input . IgnoreWordlistComments , "ic" , opts . Input . IgnoreWordlistComments , "Ignore wordlist comments" )
flag . IntVar ( & opts . General . MaxTime , "maxtime" , opts . General . MaxTime , "Maximum running time in seconds for entire process." )
flag . IntVar ( & opts . General . MaxTimeJob , "maxtime-job" , opts . General . MaxTimeJob , "Maximum running time in seconds per job." )
flag . IntVar ( & opts . General . Rate , "rate" , opts . General . Rate , "Rate of requests per second" )
flag . IntVar ( & opts . General . Threads , "t" , opts . General . Threads , "Number of concurrent threads." )
flag . IntVar ( & opts . HTTP . RecursionDepth , "recursion-depth" , opts . HTTP . RecursionDepth , "Maximum recursion depth." )
flag . IntVar ( & opts . HTTP . Timeout , "timeout" , opts . HTTP . Timeout , "HTTP request timeout in seconds." )
flag . IntVar ( & opts . Input . InputNum , "input-num" , opts . Input . InputNum , "Number of inputs to test. Used in conjunction with --input-cmd." )
2022-03-20 17:13:32 +00:00
flag . StringVar ( & opts . General . AutoCalibrationKeyword , "ack" , opts . General . AutoCalibrationKeyword , "Autocalibration keyword" )
flag . StringVar ( & opts . General . AutoCalibrationStrategy , "acs" , opts . General . AutoCalibrationStrategy , "Autocalibration strategy: \"basic\" or \"advanced\"" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . General . ConfigFile , "config" , "" , "Load configuration from a file" )
2023-02-04 11:23:31 +00:00
flag . StringVar ( & opts . General . ScraperFile , "scraperfile" , "" , "Custom scraper file path" )
flag . StringVar ( & opts . General . Scrapers , "scrapers" , opts . General . Scrapers , "Active scraper groups" )
2022-04-03 20:20:53 +00:00
flag . StringVar ( & opts . Filter . Mode , "fmode" , opts . Filter . Mode , "Filter set operator. Either of: and, or" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . Filter . Lines , "fl" , opts . Filter . Lines , "Filter by amount of lines in response. Comma separated list of line counts and ranges" )
flag . StringVar ( & opts . Filter . Regexp , "fr" , opts . Filter . Regexp , "Filter regexp" )
flag . StringVar ( & opts . Filter . Size , "fs" , opts . Filter . Size , "Filter HTTP response size. Comma separated list of sizes and ranges" )
flag . StringVar ( & opts . Filter . Status , "fc" , opts . Filter . Status , "Filter HTTP status codes from response. Comma separated list of codes and ranges" )
2021-05-16 21:10:56 +00:00
flag . StringVar ( & opts . Filter . Time , "ft" , opts . Filter . Time , "Filter by number of milliseconds to the first response byte, either greater or less than. EG: >100 or <100" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . Filter . Words , "fw" , opts . Filter . Words , "Filter by amount of words in response. Comma separated list of word counts and ranges" )
flag . StringVar ( & opts . General . Delay , "p" , opts . General . Delay , "Seconds of `delay` between requests, or a range of random delay. For example \"0.1\" or \"0.1-2.0\"" )
2023-02-02 09:51:11 +00:00
flag . StringVar ( & opts . General . Searchhash , "search" , opts . General . Searchhash , "Search for a FFUFHASH payload from ffuf history" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . HTTP . Data , "d" , opts . HTTP . Data , "POST data" )
flag . StringVar ( & opts . HTTP . Data , "data" , opts . HTTP . Data , "POST data (alias of -d)" )
flag . StringVar ( & opts . HTTP . Data , "data-ascii" , opts . HTTP . Data , "POST data (alias of -d)" )
flag . StringVar ( & opts . HTTP . Data , "data-binary" , opts . HTTP . Data , "POST data (alias of -d)" )
flag . StringVar ( & opts . HTTP . Method , "X" , opts . HTTP . Method , "HTTP method to use" )
2021-04-18 09:54:17 +00:00
flag . StringVar ( & opts . HTTP . ProxyURL , "x" , opts . HTTP . ProxyURL , "Proxy URL (SOCKS5 or HTTP). For example: http://127.0.0.1:8080 or socks5://127.0.0.1:8080" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . HTTP . ReplayProxyURL , "replay-proxy" , opts . HTTP . ReplayProxyURL , "Replay matched requests using this proxy." )
2021-04-18 09:54:17 +00:00
flag . StringVar ( & opts . HTTP . RecursionStrategy , "recursion-strategy" , opts . HTTP . RecursionStrategy , "Recursion strategy: \"default\" for a redirect based, and \"greedy\" to recurse on all matches" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . HTTP . URL , "u" , opts . HTTP . URL , "Target URL" )
2021-05-13 20:46:29 +00:00
flag . StringVar ( & opts . HTTP . SNI , "sni" , opts . HTTP . SNI , "Target TLS SNI, does not support FUZZ keyword" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . Input . Extensions , "e" , opts . Input . Extensions , "Comma separated list of extensions. Extends FUZZ keyword." )
2022-03-06 14:14:45 +00:00
flag . StringVar ( & opts . Input . InputMode , "mode" , opts . Input . InputMode , "Multi-wordlist operation mode. Available modes: clusterbomb, pitchfork, sniper" )
2021-01-24 16:55:23 +00:00
flag . StringVar ( & opts . Input . InputShell , "input-shell" , opts . Input . InputShell , "Shell to be used for running command" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . Input . Request , "request" , opts . Input . Request , "File containing the raw http request" )
flag . StringVar ( & opts . Input . RequestProto , "request-proto" , opts . Input . RequestProto , "Protocol to use along with raw request" )
2022-04-03 20:20:53 +00:00
flag . StringVar ( & opts . Matcher . Mode , "mmode" , opts . Matcher . Mode , "Matcher set operator. Either of: and, or" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . Matcher . Lines , "ml" , opts . Matcher . Lines , "Match amount of lines in response" )
flag . StringVar ( & opts . Matcher . Regexp , "mr" , opts . Matcher . Regexp , "Match regexp" )
flag . StringVar ( & opts . Matcher . Size , "ms" , opts . Matcher . Size , "Match HTTP response size" )
flag . StringVar ( & opts . Matcher . Status , "mc" , opts . Matcher . Status , "Match HTTP status codes, or \"all\" for everything." )
2021-05-16 21:10:56 +00:00
flag . StringVar ( & opts . Matcher . Time , "mt" , opts . Matcher . Time , "Match how many milliseconds to the first response byte, either greater or less than. EG: >100 or <100" )
2020-09-27 16:24:06 +00:00
flag . StringVar ( & opts . Matcher . Words , "mw" , opts . Matcher . Words , "Match amount of words in response" )
flag . StringVar ( & opts . Output . DebugLog , "debug-log" , opts . Output . DebugLog , "Write all of the internal logging to the specified file." )
flag . StringVar ( & opts . Output . OutputDirectory , "od" , opts . Output . OutputDirectory , "Directory path to store matched results to." )
flag . StringVar ( & opts . Output . OutputFile , "o" , opts . Output . OutputFile , "Write output to file" )
flag . StringVar ( & opts . Output . OutputFormat , "of" , opts . Output . OutputFormat , "Output file format. Available formats: json, ejson, html, md, csv, ecsv (or, 'all' for all formats)" )
flag . Var ( & autocalibrationstrings , "acc" , "Custom auto-calibration string. Can be used multiple times. Implies -ac" )
flag . Var ( & cookies , "b" , "Cookie data `\"NAME1=VALUE1; NAME2=VALUE2\"` for copy as curl functionality." )
flag . Var ( & cookies , "cookie" , "Cookie data (alias of -b)" )
flag . Var ( & headers , "H" , "Header `\"Name: Value\"`, separated by colon. Multiple -H flags are accepted." )
flag . Var ( & inputcommands , "input-cmd" , "Command producing the input. --input-num is required when using this input method. Overrides -w." )
flag . Var ( & wordlists , "w" , "Wordlist file path and (optional) keyword separated by colon. eg. '/path/to/wordlist:KEYWORD'" )
2020-01-29 22:23:58 +00:00
flag . Usage = Usage
2018-11-08 09:26:32 +00:00
flag . Parse ( )
2020-09-27 16:24:06 +00:00
opts . General . AutoCalibrationStrings = autocalibrationstrings
opts . HTTP . Cookies = cookies
opts . HTTP . Headers = headers
opts . Input . Inputcommands = inputcommands
opts . Input . Wordlists = wordlists
return opts
}
func main ( ) {
var err , optserr error
2023-02-02 09:51:11 +00:00
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
2020-09-27 16:24:06 +00:00
// prepare the default config options from default config file
var opts * ffuf . ConfigOptions
opts , optserr = ffuf . ReadDefaultConfig ( )
opts = ParseFlags ( opts )
2023-02-02 09:51:11 +00:00
// Handle searchhash functionality and exit
if opts . General . Searchhash != "" {
coptions , pos , err := ffuf . SearchHash ( opts . General . Searchhash )
if err != nil {
fmt . Printf ( "[ERR] %s\n" , err )
os . Exit ( 1 )
}
if len ( coptions ) > 0 {
fmt . Printf ( "Request candidate(s) for hash %s\n" , opts . General . Searchhash )
}
for _ , copt := range coptions {
conf , err := ffuf . ConfigFromOptions ( & copt . ConfigOptions , ctx , cancel )
if err != nil {
continue
}
2023-02-04 11:36:00 +00:00
ok , reason := ffuf . HistoryReplayable ( conf )
if ok {
printSearchResults ( conf , pos , copt . Time , opts . General . Searchhash )
} else {
fmt . Printf ( "[ERR] Hash cannot be mapped back because %s\n" , reason )
}
2023-02-02 09:51:11 +00:00
}
if err != nil {
fmt . Printf ( "[ERR] %s\n" , err )
}
os . Exit ( 0 )
}
2020-09-27 16:24:06 +00:00
if opts . General . ShowVersion {
2021-03-04 20:04:04 +00:00
fmt . Printf ( "ffuf version: %s\n" , ffuf . Version ( ) )
2018-11-15 08:47:43 +00:00
os . Exit ( 0 )
}
2020-09-27 16:24:06 +00:00
if len ( opts . Output . DebugLog ) != 0 {
f , err := os . OpenFile ( opts . Output . DebugLog , os . O_APPEND | os . O_CREATE | os . O_WRONLY , 0644 )
2019-10-20 15:38:11 +00:00
if err != nil {
fmt . Fprintf ( os . Stderr , "Disabling logging, encountered error(s): %s\n" , err )
2023-02-02 09:51:11 +00:00
log . SetOutput ( io . Discard )
2019-10-20 15:38:11 +00:00
} else {
log . SetOutput ( f )
defer f . Close ( )
}
} else {
2023-02-02 09:51:11 +00:00
log . SetOutput ( io . Discard )
2019-10-20 15:38:11 +00:00
}
2020-09-27 16:24:06 +00:00
if optserr != nil {
log . Printf ( "Error while opening default config file: %s" , optserr )
}
if opts . General . ConfigFile != "" {
opts , err = ffuf . ReadConfig ( opts . General . ConfigFile )
if err != nil {
fmt . Fprintf ( os . Stderr , "Encoutered error(s): %s\n" , err )
Usage ( )
fmt . Fprintf ( os . Stderr , "Encoutered error(s): %s\n" , err )
os . Exit ( 1 )
}
// Reset the flag package state
flag . CommandLine = flag . NewFlagSet ( os . Args [ 0 ] , flag . ExitOnError )
// Re-parse the cli options
opts = ParseFlags ( opts )
}
2023-02-02 09:51:11 +00:00
// Set up Config struct
2020-09-27 16:24:06 +00:00
conf , err := ffuf . ConfigFromOptions ( opts , ctx , cancel )
if err != nil {
2018-11-08 13:54:12 +00:00
fmt . Fprintf ( os . Stderr , "Encountered error(s): %s\n" , err )
2020-01-29 22:23:58 +00:00
Usage ( )
2020-08-30 12:22:06 +00:00
fmt . Fprintf ( os . Stderr , "Encountered error(s): %s\n" , err )
2018-11-08 09:26:32 +00:00
os . Exit ( 1 )
}
2023-02-02 09:51:11 +00:00
2020-09-27 16:24:06 +00:00
job , err := prepareJob ( conf )
2019-04-28 16:36:48 +00:00
if err != nil {
2018-11-08 13:54:12 +00:00
fmt . Fprintf ( os . Stderr , "Encountered error(s): %s\n" , err )
2020-01-29 22:23:58 +00:00
Usage ( )
2020-08-30 12:22:06 +00:00
fmt . Fprintf ( os . Stderr , "Encountered error(s): %s\n" , err )
2018-11-08 09:26:32 +00:00
os . Exit ( 1 )
}
2022-03-20 17:13:32 +00:00
if err := SetupFilters ( opts , conf ) ; err != nil {
2018-11-08 13:54:12 +00:00
fmt . Fprintf ( os . Stderr , "Encountered error(s): %s\n" , err )
2020-01-29 22:23:58 +00:00
Usage ( )
2020-08-30 12:22:06 +00:00
fmt . Fprintf ( os . Stderr , "Encountered error(s): %s\n" , err )
2018-11-08 09:26:32 +00:00
os . Exit ( 1 )
}
2019-04-20 17:46:43 +00:00
2021-04-26 20:04:12 +00:00
if ! conf . Noninteractive {
go func ( ) {
err := interactive . Handle ( job )
if err != nil {
log . Printf ( "Error while trying to initialize interactive session: %s" , err )
}
} ( )
}
2019-04-20 17:46:43 +00:00
2018-11-08 09:26:32 +00:00
// Job handles waiting for goroutines to complete itself
job . Start ( )
}
func prepareJob ( conf * ffuf . Config ) ( * ffuf . Job , error ) {
2023-02-04 11:23:31 +00:00
var err error
2020-08-30 10:51:41 +00:00
job := ffuf . NewJob ( conf )
2020-09-27 16:24:06 +00:00
var errs ffuf . Multierror
job . Input , errs = input . NewInputProvider ( conf )
2018-11-08 09:26:32 +00:00
// TODO: implement error handling for runnerprovider and outputprovider
// We only have http runner right now
2020-01-17 07:49:25 +00:00
job . Runner = runner . NewRunnerByName ( "http" , conf , false )
if len ( conf . ReplayProxyURL ) > 0 {
job . ReplayRunner = runner . NewRunnerByName ( "http" , conf , true )
}
2018-11-08 09:26:32 +00:00
// We only have stdout outputprovider right now
2020-01-17 07:49:25 +00:00
job . Output = output . NewOutputProviderByName ( "stdout" , conf )
2023-02-04 11:23:31 +00:00
// Initialize scraper
newscraper , scraper_err := scraper . FromDir ( ffuf . SCRAPERDIR , conf . Scrapers )
if scraper_err . ErrorOrNil ( ) != nil {
errs . Add ( scraper_err . ErrorOrNil ( ) )
}
job . Scraper = newscraper
if conf . ScraperFile != "" {
err = job . Scraper . AppendFromFile ( conf . ScraperFile )
if err != nil {
errs . Add ( err )
}
}
2020-01-17 07:49:25 +00:00
return job , errs . ErrorOrNil ( )
2018-11-08 09:26:32 +00:00
}
2022-03-20 17:13:32 +00:00
func SetupFilters ( parseOpts * ffuf . ConfigOptions , conf * ffuf . Config ) error {
errs := ffuf . NewMultierror ( )
conf . MatcherManager = filter . NewMatcherManager ( )
// If any other matcher is set, ignore -mc default value
matcherSet := false
statusSet := false
warningIgnoreBody := false
flag . Visit ( func ( f * flag . Flag ) {
if f . Name == "mc" {
statusSet = true
}
if f . Name == "ms" {
matcherSet = true
warningIgnoreBody = true
}
if f . Name == "ml" {
matcherSet = true
warningIgnoreBody = true
}
if f . Name == "mr" {
matcherSet = true
}
if f . Name == "mt" {
matcherSet = true
}
if f . Name == "mw" {
matcherSet = true
warningIgnoreBody = true
}
} )
// Only set default matchers if no
if statusSet || ! matcherSet {
if err := conf . MatcherManager . AddMatcher ( "status" , parseOpts . Matcher . Status ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Filter . Status != "" {
if err := conf . MatcherManager . AddFilter ( "status" , parseOpts . Filter . Status , false ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Filter . Size != "" {
warningIgnoreBody = true
if err := conf . MatcherManager . AddFilter ( "size" , parseOpts . Filter . Size , false ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Filter . Regexp != "" {
if err := conf . MatcherManager . AddFilter ( "regexp" , parseOpts . Filter . Regexp , false ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Filter . Words != "" {
warningIgnoreBody = true
if err := conf . MatcherManager . AddFilter ( "word" , parseOpts . Filter . Words , false ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Filter . Lines != "" {
warningIgnoreBody = true
if err := conf . MatcherManager . AddFilter ( "line" , parseOpts . Filter . Lines , false ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Filter . Time != "" {
if err := conf . MatcherManager . AddFilter ( "time" , parseOpts . Filter . Time , false ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Matcher . Size != "" {
if err := conf . MatcherManager . AddMatcher ( "size" , parseOpts . Matcher . Size ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Matcher . Regexp != "" {
if err := conf . MatcherManager . AddMatcher ( "regexp" , parseOpts . Matcher . Regexp ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Matcher . Words != "" {
if err := conf . MatcherManager . AddMatcher ( "word" , parseOpts . Matcher . Words ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Matcher . Lines != "" {
if err := conf . MatcherManager . AddMatcher ( "line" , parseOpts . Matcher . Lines ) ; err != nil {
errs . Add ( err )
}
}
if parseOpts . Matcher . Time != "" {
2023-02-02 14:08:57 +00:00
if err := conf . MatcherManager . AddMatcher ( "time" , parseOpts . Matcher . Time ) ; err != nil {
2022-03-20 17:13:32 +00:00
errs . Add ( err )
}
}
if conf . IgnoreBody && warningIgnoreBody {
fmt . Printf ( "*** Warning: possible undesired combination of -ignore-body and the response options: fl,fs,fw,ml,ms and mw.\n" )
}
return errs . ErrorOrNil ( )
}
2023-02-02 09:51:11 +00:00
func printSearchResults ( conf * ffuf . Config , pos int , exectime time . Time , hash string ) {
inp , err := input . NewInputProvider ( conf )
if err . ErrorOrNil ( ) != nil {
fmt . Printf ( "-------------------------------------------\n" )
fmt . Println ( "Encountered error that prevents reproduction of the request:" )
fmt . Println ( err . ErrorOrNil ( ) )
return
}
inp . SetPosition ( pos )
inputdata := inp . Value ( )
inputdata [ "FFUFHASH" ] = [ ] byte ( hash )
basereq := ffuf . BaseRequest ( conf )
dummyrunner := runner . NewRunnerByName ( "simple" , conf , false )
ffufreq , _ := dummyrunner . Prepare ( inputdata , & basereq )
rawreq , _ := dummyrunner . Dump ( & ffufreq )
fmt . Printf ( "-------------------------------------------\n" )
fmt . Printf ( "ffuf job started at: %s\n\n" , exectime . Format ( time . RFC3339 ) )
fmt . Printf ( "%s\n" , string ( rawreq ) )
}