New flag to stop on spurious 403 responses
This commit is contained in:
parent
3f3b5c31db
commit
e9f2dfd1c9
1
main.go
1
main.go
@ -66,6 +66,7 @@ func main() {
|
||||
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.BoolVar(&conf.StopOn403, "sf", false, "Stop when > 90% of responses return 403 Forbidden")
|
||||
flag.IntVar(&conf.Threads, "t", 40, "Number of concurrent threads.")
|
||||
flag.BoolVar(&opts.showVersion, "V", false, "Show version information.")
|
||||
flag.Parse()
|
||||
|
||||
@ -25,6 +25,7 @@ type Config struct {
|
||||
Quiet bool
|
||||
Colors bool
|
||||
Wordlist string
|
||||
StopOn403 bool
|
||||
Delay optRange
|
||||
Filters []FilterProvider
|
||||
Matchers []FilterProvider
|
||||
@ -43,6 +44,7 @@ func NewConfig(ctx context.Context) Config {
|
||||
conf.TLSSkipVerify = false
|
||||
conf.Data = ""
|
||||
conf.Quiet = false
|
||||
conf.StopOn403 = false
|
||||
conf.ProxyURL = http.ProxyFromEnvironment
|
||||
conf.Filters = make([]FilterProvider, 0)
|
||||
conf.Delay = optRange{0, 0, false, false}
|
||||
|
||||
@ -23,6 +23,8 @@ type InputProvider interface {
|
||||
type OutputProvider interface {
|
||||
Banner() error
|
||||
Finalize() error
|
||||
Progress(status string)
|
||||
Error(errstring string)
|
||||
Warning(warnstring string)
|
||||
Result(resp Response) bool
|
||||
}
|
||||
|
||||
@ -16,6 +16,8 @@ type Job struct {
|
||||
Counter int
|
||||
Total int
|
||||
Running bool
|
||||
Count403 int
|
||||
Error string
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
@ -42,6 +44,12 @@ func (j *Job) Start() {
|
||||
//Limiter blocks after reaching the buffer, ensuring limited concurrency
|
||||
limiter := make(chan bool, j.Config.Threads)
|
||||
for j.Input.Next() {
|
||||
// Check if we should stop the process
|
||||
j.CheckStop()
|
||||
if !j.Running {
|
||||
defer j.Output.Warning(j.Error)
|
||||
break
|
||||
}
|
||||
limiter <- true
|
||||
nextInput := j.Input.Value()
|
||||
wg.Add(1)
|
||||
@ -73,6 +81,9 @@ func (j *Job) runProgress(wg *sync.WaitGroup) {
|
||||
j.startTime = time.Now()
|
||||
totalProgress := j.Input.Total()
|
||||
for j.Counter <= totalProgress {
|
||||
if !j.Running {
|
||||
break
|
||||
}
|
||||
j.updateProgress()
|
||||
if j.Counter == totalProgress {
|
||||
return
|
||||
@ -82,11 +93,6 @@ func (j *Job) runProgress(wg *sync.WaitGroup) {
|
||||
}
|
||||
|
||||
func (j *Job) updateProgress() {
|
||||
//TODO: refactor to use a defined progress struct for future output modules
|
||||
if j.Config.Quiet {
|
||||
// Do not print progress status in silent mode
|
||||
return
|
||||
}
|
||||
runningSecs := int((time.Now().Sub(j.startTime)) / time.Second)
|
||||
var reqRate int
|
||||
if runningSecs > 0 {
|
||||
@ -101,7 +107,7 @@ func (j *Job) updateProgress() {
|
||||
dur -= mins * time.Minute
|
||||
secs := dur / time.Second
|
||||
progString := fmt.Sprintf(":: Progress: [%d/%d] :: %d req/sec :: Duration: [%d:%02d:%02d] ::", j.Counter, j.Total, int(reqRate), hours, mins, secs)
|
||||
j.Output.Error(progString)
|
||||
j.Output.Progress(progString)
|
||||
}
|
||||
|
||||
func (j *Job) runTask(input []byte) {
|
||||
@ -115,6 +121,12 @@ func (j *Job) runTask(input []byte) {
|
||||
j.Output.Error(fmt.Sprintf("Error in runner: %s\n", err))
|
||||
return
|
||||
}
|
||||
if j.Config.StopOn403 {
|
||||
// Incremnt Forbidden counter if we encountered one
|
||||
if resp.StatusCode == 403 {
|
||||
j.Count403 += 1
|
||||
}
|
||||
}
|
||||
if j.Output.Result(resp) {
|
||||
// Refresh the progress indicator as we printed something out
|
||||
j.updateProgress()
|
||||
@ -122,6 +134,17 @@ func (j *Job) runTask(input []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
func (j *Job) CheckStop() {
|
||||
if j.Counter > 50 {
|
||||
// We have enough samples
|
||||
if float64(j.Count403)/float64(j.Counter) > 0.95 {
|
||||
// Over 95% of requests are 403
|
||||
j.Error = "Getting unusual amount of 403 responses, exiting."
|
||||
j.Stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Stop the execution of the Job
|
||||
func (j *Job) Stop() {
|
||||
j.Running = false
|
||||
|
||||
@ -43,11 +43,36 @@ func (s *Stdoutput) Banner() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Stdoutput) Progress(status string) {
|
||||
if s.config.Quiet {
|
||||
// No progress for quiet mode
|
||||
return
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s%s", TERMINAL_CLEAR_LINE, status)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Stdoutput) Error(errstring string) {
|
||||
if s.config.Quiet {
|
||||
fmt.Fprintf(os.Stderr, "%s", errstring)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s%s", TERMINAL_CLEAR_LINE, errstring)
|
||||
if !s.config.Colors {
|
||||
fmt.Fprintf(os.Stderr, "%s[ERR] %s\n", TERMINAL_CLEAR_LINE, errstring)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s[%sERR%s] %s\n", TERMINAL_CLEAR_LINE, ANSI_RED, ANSI_CLEAR, errstring)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Stdoutput) Warning(warnstring string) {
|
||||
if s.config.Quiet {
|
||||
fmt.Fprintf(os.Stderr, "%s", warnstring)
|
||||
} else {
|
||||
if !s.config.Colors {
|
||||
fmt.Fprintf(os.Stderr, "%s[WARN] %s", TERMINAL_CLEAR_LINE, warnstring)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s[%sWARN%s] %s\n", TERMINAL_CLEAR_LINE, ANSI_RED, ANSI_CLEAR, warnstring)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user