mirror of
https://github.com/ffuf/ffuf
synced 2024-11-10 06:04:17 +00:00
commit
0818256e1d
4 changed files with 59 additions and 7 deletions
|
@ -71,9 +71,9 @@ ffuf -w /path/to/postdata.txt -X POST -d "username=admin\&password=FUZZ" https:/
|
|||
To define the test case for ffuf, use the keyword `FUZZ` anywhere in the URL (`-u`), headers (`-H`), or POST data (`-d`).
|
||||
|
||||
```
|
||||
Usage of ./ffuf:
|
||||
-H "Name: Value"
|
||||
Header "Name: Value", separated by colon. Multiple -H flags are accepted.
|
||||
-V Show version information.
|
||||
-X string
|
||||
HTTP method to use. (default "GET")
|
||||
-c Colorize output.
|
||||
|
@ -89,13 +89,15 @@ Usage of ./ffuf:
|
|||
Filter by amount of words in response
|
||||
-k Skip TLS identity verification (insecure)
|
||||
-mc string
|
||||
Match HTTP status codes from respose (default "200,204,301,302,307,401")
|
||||
Match HTTP status codes from respose (default "200,204,301,302,307,401,403")
|
||||
-mr string
|
||||
Match regexp
|
||||
-ms string
|
||||
Match HTTP response size
|
||||
-mw string
|
||||
Match amount of words in response
|
||||
-p delay
|
||||
Seconds of delay between requests, or a range of random delay. For example "0.1" or "0.1-2.0"
|
||||
-s Do not print additional information (silent mode)
|
||||
-t int
|
||||
Number of concurrent threads. (default 40)
|
||||
|
|
37
main.go
37
main.go
|
@ -5,6 +5,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ffuf/ffuf/pkg/ffuf"
|
||||
|
@ -15,6 +16,7 @@ import (
|
|||
)
|
||||
|
||||
type cliOptions struct {
|
||||
delay string
|
||||
filterStatus string
|
||||
filterSize string
|
||||
filterRegexp string
|
||||
|
@ -23,18 +25,18 @@ type cliOptions struct {
|
|||
matcherSize string
|
||||
matcherRegexp string
|
||||
matcherWords string
|
||||
headers headerFlags
|
||||
headers multiStringFlag
|
||||
showVersion bool
|
||||
}
|
||||
|
||||
type headerFlags []string
|
||||
type multiStringFlag []string
|
||||
|
||||
func (h *headerFlags) String() string {
|
||||
func (m *multiStringFlag) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (h *headerFlags) Set(value string) error {
|
||||
*h = append(*h, value)
|
||||
func (m *multiStringFlag) Set(value string) error {
|
||||
*m = append(*m, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -47,6 +49,7 @@ func main() {
|
|||
flag.StringVar(&conf.Url, "u", "", "Target URL")
|
||||
flag.StringVar(&conf.Wordlist, "w", "", "Wordlist path")
|
||||
flag.BoolVar(&conf.TLSSkipVerify, "k", false, "Skip TLS identity verification (insecure)")
|
||||
flag.StringVar(&opts.delay, "p", "", "Seconds of `delay` between requests, or a range of random delay. For example \"0.1\" or \"0.1-2.0\"")
|
||||
flag.StringVar(&opts.filterStatus, "fc", "", "Filter HTTP status codes from response")
|
||||
flag.StringVar(&opts.filterSize, "fs", "", "Filter HTTP response size")
|
||||
flag.StringVar(&opts.filterRegexp, "fr", "", "Filter regexp")
|
||||
|
@ -111,6 +114,9 @@ func prepareConfig(parseOpts *cliOptions, conf *ffuf.Config) error {
|
|||
//TODO: refactor in a proper flag library that can handle things like required flags
|
||||
errs := ffuf.NewMultierror()
|
||||
foundkeyword := false
|
||||
|
||||
var err error
|
||||
var err2 error
|
||||
if len(conf.Url) == 0 {
|
||||
errs.Add(fmt.Errorf("-u flag is required"))
|
||||
}
|
||||
|
@ -138,6 +144,27 @@ func prepareConfig(parseOpts *cliOptions, conf *ffuf.Config) error {
|
|||
errs.Add(fmt.Errorf("Header defined by -H needs to have a value. \":\" should be used as a separator"))
|
||||
}
|
||||
}
|
||||
//Prepare delay
|
||||
d := strings.Split(parseOpts.delay, "-")
|
||||
if len(d) > 2 {
|
||||
errs.Add(fmt.Errorf("Delay needs to be either a single float: \"0.1\" or a range of floats, delimited by dash: \"0.1-0.8\""))
|
||||
} else if len(d) == 2 {
|
||||
conf.Delay.IsRange = true
|
||||
conf.Delay.HasDelay = true
|
||||
conf.Delay.Min, err = strconv.ParseFloat(d[0], 64)
|
||||
conf.Delay.Max, err2 = strconv.ParseFloat(d[1], 64)
|
||||
if err != nil || err2 != nil {
|
||||
errs.Add(fmt.Errorf("Delay range min and max values need to be valid floats. For example: 0.1-0.5"))
|
||||
}
|
||||
} else if len(parseOpts.delay) > 0 {
|
||||
conf.Delay.IsRange = false
|
||||
conf.Delay.HasDelay = true
|
||||
conf.Delay.Min, err = strconv.ParseFloat(parseOpts.delay, 64)
|
||||
if err != nil {
|
||||
errs.Add(fmt.Errorf("Delay needs to be either a single float: \"0.1\" or a range of floats, delimited by dash: \"0.1-0.8\""))
|
||||
}
|
||||
}
|
||||
|
||||
//Search for keyword from URL and POST data too
|
||||
if strings.Index(conf.Url, "FUZZ") != -1 {
|
||||
foundkeyword = true
|
||||
|
|
|
@ -4,6 +4,15 @@ import (
|
|||
"context"
|
||||
)
|
||||
|
||||
//optRange stores either a single float, in which case the value is stored in min and IsRange is false,
|
||||
//or a range of floats, in which case IsRange is true
|
||||
type optRange struct {
|
||||
Min float64
|
||||
Max float64
|
||||
IsRange bool
|
||||
HasDelay bool
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
StaticHeaders map[string]string
|
||||
FuzzHeaders map[string]string
|
||||
|
@ -14,6 +23,7 @@ type Config struct {
|
|||
Quiet bool
|
||||
Colors bool
|
||||
Wordlist string
|
||||
Delay optRange
|
||||
Filters []FilterProvider
|
||||
Matchers []FilterProvider
|
||||
Threads int
|
||||
|
@ -31,5 +41,6 @@ func NewConfig(ctx context.Context) Config {
|
|||
conf.Data = ""
|
||||
conf.Quiet = false
|
||||
conf.Filters = make([]FilterProvider, 0)
|
||||
conf.Delay = optRange{0, 0, false, false}
|
||||
return conf
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package ffuf
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
@ -27,6 +28,7 @@ func NewJob(conf *Config) Job {
|
|||
|
||||
//Start the execution of the Job
|
||||
func (j *Job) Start() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
j.Total = j.Input.Total()
|
||||
defer j.Stop()
|
||||
//Show banner if not running in silent mode
|
||||
|
@ -48,6 +50,16 @@ func (j *Job) Start() {
|
|||
defer func() { <-limiter }()
|
||||
defer wg.Done()
|
||||
j.runTask([]byte(nextInput))
|
||||
if j.Config.Delay.HasDelay {
|
||||
var sleepDurationMS time.Duration
|
||||
if j.Config.Delay.IsRange {
|
||||
sTime := j.Config.Delay.Min + rand.Float64()*(j.Config.Delay.Max-j.Config.Delay.Min)
|
||||
sleepDurationMS = time.Duration(sTime * 1000)
|
||||
} else {
|
||||
sleepDurationMS = time.Duration(j.Config.Delay.Min * 1000)
|
||||
}
|
||||
time.Sleep(sleepDurationMS * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
|
Loading…
Reference in a new issue