diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b94f8e..32c39af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - New - Added a CLI flag to disable the interactive mode - Changed + - Fixed an issue with storing the matches for recursion jobs - Fixed the way the "size" is calculated, it should match content-length now - Fixed an issue with header canonicalization when a keyword was just a part of the header name - Fixed output writing so it doesn't silently fail if it needs to create directories recursively diff --git a/README.md b/README.md index 86a4e27..69c6b3f 100644 --- a/README.md +++ b/README.md @@ -263,7 +263,7 @@ available commands: queueskip - advance to the next queued recursion job restart - restart and resume the current ffuf job resume - resume current ffuf job (or: ENTER) - show - show results + show - show results for the current job savejson [filename] - save current matches to a file help - you are looking at it > diff --git a/pkg/ffuf/interfaces.go b/pkg/ffuf/interfaces.go index c356444..048b8c3 100644 --- a/pkg/ffuf/interfaces.go +++ b/pkg/ffuf/interfaces.go @@ -46,9 +46,10 @@ type OutputProvider interface { Result(resp Response) PrintResult(res Result) SaveFile(filename, format string) error - GetResults() []Result - SetResults(results []Result) + GetCurrentResults() []Result + SetCurrentResults(results []Result) Reset() + Cycle() } type Result struct { diff --git a/pkg/ffuf/job.go b/pkg/ffuf/job.go index 22c0da3..00ee641 100644 --- a/pkg/ffuf/job.go +++ b/pkg/ffuf/job.go @@ -123,7 +123,7 @@ func (j *Job) Start() { j.interruptMonitor() for j.jobsInQueue() { j.prepareQueueJob() - j.Reset() + j.Reset(true) j.RunningJob = true j.startExecution() } @@ -135,12 +135,16 @@ func (j *Job) Start() { } // Reset resets the counters and wordlist position for a job -func (j *Job) Reset() { +func (j *Job) Reset(cycle bool) { j.Input.Reset() j.Counter = 0 j.skipQueue = false j.startTimeJob = time.Now() - j.Output.Reset() + if cycle { + j.Output.Cycle() + } else { + j.Output.Reset() + } } func (j *Job) jobsInQueue() bool { diff --git a/pkg/interactive/termhandler.go b/pkg/interactive/termhandler.go index 24a5781..bade761 100644 --- a/pkg/interactive/termhandler.go +++ b/pkg/interactive/termhandler.go @@ -53,12 +53,12 @@ func (i *interactive) handleInput(in []byte) { i.paused = false i.Job.Resume() case "restart": - i.Job.Reset() + i.Job.Reset(false) i.paused = false i.Job.Output.Info("Restarting the current ffuf job!") i.Job.Resume() case "show": - for _, r := range i.Job.Output.GetResults() { + for _, r := range i.Job.Output.GetCurrentResults() { i.Job.Output.PrintResult(r) } case "savejson": @@ -150,7 +150,7 @@ func (i *interactive) updateFilter(name, value string) { } results := make([]ffuf.Result, 0) - for _, res := range i.Job.Output.GetResults() { + for _, res := range i.Job.Output.GetCurrentResults() { fakeResp := &ffuf.Response{ StatusCode: res.StatusCode, ContentLines: res.ContentLength, @@ -162,7 +162,7 @@ func (i *interactive) updateFilter(name, value string) { results = append(results, res) } } - i.Job.Output.SetResults(results) + i.Job.Output.SetCurrentResults(results) } } @@ -229,7 +229,7 @@ available commands: queueskip - advance to the next queued recursion job restart - restart and resume the current ffuf job resume - resume current ffuf job (or: ENTER) - show - show results + show - show results for the current job savejson [filename] - save current matches to a file help - you are looking at it ` diff --git a/pkg/output/stdout.go b/pkg/output/stdout.go index 1b72092..043427c 100644 --- a/pkg/output/stdout.go +++ b/pkg/output/stdout.go @@ -26,14 +26,16 @@ const ( ) type Stdoutput struct { - config *ffuf.Config - Results []ffuf.Result + config *ffuf.Config + Results []ffuf.Result + CurrentResults []ffuf.Result } func NewStdoutput(conf *ffuf.Config) *Stdoutput { var outp Stdoutput outp.config = conf - outp.Results = []ffuf.Result{} + outp.Results = make([]ffuf.Result, 0) + outp.CurrentResults = make([]ffuf.Result, 0) return &outp } @@ -133,17 +135,23 @@ func (s *Stdoutput) Banner() { // Reset resets the result slice func (s *Stdoutput) Reset() { - s.Results = make([]ffuf.Result, 0) + s.CurrentResults = make([]ffuf.Result, 0) +} + +// Cycle moves the CurrentResults to Results and resets the results slice +func (s *Stdoutput) Cycle() { + s.Results = append(s.Results, s.CurrentResults...) + s.Reset() } // GetResults returns the result slice -func (s *Stdoutput) GetResults() []ffuf.Result { - return s.Results +func (s *Stdoutput) GetCurrentResults() []ffuf.Result { + return s.CurrentResults } // SetResults sets the result slice -func (s *Stdoutput) SetResults(results []ffuf.Result) { - s.Results = results +func (s *Stdoutput) SetCurrentResults(results []ffuf.Result) { + s.CurrentResults = results } func (s *Stdoutput) Progress(status ffuf.Progress) { @@ -222,37 +230,37 @@ func (s *Stdoutput) writeToAll(filename string, config *ffuf.Config, res []ffuf. } s.config.OutputFile = BaseFilename + ".json" - err = writeJSON(filename, s.config, s.Results) + err = writeJSON(filename, s.config, res) if err != nil { s.Error(err.Error()) } s.config.OutputFile = BaseFilename + ".ejson" - err = writeEJSON(filename, s.config, s.Results) + err = writeEJSON(filename, s.config, res) if err != nil { s.Error(err.Error()) } s.config.OutputFile = BaseFilename + ".html" - err = writeHTML(filename, s.config, s.Results) + err = writeHTML(filename, s.config, res) if err != nil { s.Error(err.Error()) } s.config.OutputFile = BaseFilename + ".md" - err = writeMarkdown(filename, s.config, s.Results) + err = writeMarkdown(filename, s.config, res) if err != nil { s.Error(err.Error()) } s.config.OutputFile = BaseFilename + ".csv" - err = writeCSV(filename, s.config, s.Results, false) + err = writeCSV(filename, s.config, res, false) if err != nil { s.Error(err.Error()) } s.config.OutputFile = BaseFilename + ".ecsv" - err = writeCSV(filename, s.config, s.Results, true) + err = writeCSV(filename, s.config, res, true) if err != nil { s.Error(err.Error()) } @@ -266,19 +274,19 @@ func (s *Stdoutput) SaveFile(filename, format string) error { var err error switch format { case "all": - err = s.writeToAll(filename, s.config, s.Results) + err = s.writeToAll(filename, s.config, append(s.Results, s.CurrentResults...)) case "json": - err = writeJSON(filename, s.config, s.Results) + err = writeJSON(filename, s.config, append(s.Results, s.CurrentResults...)) case "ejson": - err = writeEJSON(filename, s.config, s.Results) + err = writeEJSON(filename, s.config, append(s.Results, s.CurrentResults...)) case "html": - err = writeHTML(filename, s.config, s.Results) + err = writeHTML(filename, s.config, append(s.Results, s.CurrentResults...)) case "md": - err = writeMarkdown(filename, s.config, s.Results) + err = writeMarkdown(filename, s.config, append(s.Results, s.CurrentResults...)) case "csv": - err = writeCSV(filename, s.config, s.Results, false) + err = writeCSV(filename, s.config, append(s.Results, s.CurrentResults...), false) case "ecsv": - err = writeCSV(filename, s.config, s.Results, true) + err = writeCSV(filename, s.config, append(s.Results, s.CurrentResults...), true) } return err } @@ -319,7 +327,7 @@ func (s *Stdoutput) Result(resp ffuf.Response) { ResultFile: resp.ResultFile, Host: resp.Request.Host, } - s.Results = append(s.Results, sResult) + s.CurrentResults = append(s.CurrentResults, sResult) // Output the result s.PrintResult(sResult) }