Option for JSON file output

This commit is contained in:
Joona Hoikkala 2019-03-30 01:02:41 +02:00
parent 3f3b5c31db
commit baa8bdb6b5
No known key found for this signature in database
GPG key ID: D5AA86BBF9B29A5C
4 changed files with 87 additions and 1 deletions

22
main.go
View file

@ -28,6 +28,7 @@ type cliOptions struct {
matcherRegexp string
matcherWords string
proxyURL string
outputFormat string
headers multiStringFlag
showVersion bool
}
@ -65,6 +66,8 @@ func main() {
flag.StringVar(&opts.matcherWords, "mw", "", "Match amount of words in response")
flag.StringVar(&opts.proxyURL, "x", "", "HTTP Proxy URL")
flag.StringVar(&conf.Method, "X", "GET", "HTTP method to use")
flag.StringVar(&conf.OutputFile, "o", "", "Write output to file")
flag.StringVar(&opts.outputFormat, "of", "json", "Output file format. Available formats: json")
flag.BoolVar(&conf.Quiet, "s", false, "Do not print additional information (silent mode)")
flag.IntVar(&conf.Threads, "t", 40, "Number of concurrent threads.")
flag.BoolVar(&opts.showVersion, "V", false, "Show version information.")
@ -179,6 +182,24 @@ func prepareConfig(parseOpts *cliOptions, conf *ffuf.Config) error {
}
}
//Check the output file format option
if conf.OutputFile != "" {
//No need to check / error out if output file isn't defined
outputFormats := []string{"json"}
found := false
for _, f := range outputFormats {
if f == parseOpts.outputFormat {
conf.OutputFormat = f
found = true
}
}
if !found {
errs.Add(fmt.Errorf("Unknown output file format (-of): %s", parseOpts.outputFormat))
}
}
conf.CommandLine = strings.Join(os.Args, " ")
//Search for keyword from URL and POST data too
if strings.Index(conf.Url, "FUZZ") != -1 {
foundkeyword = true
@ -190,6 +211,7 @@ func prepareConfig(parseOpts *cliOptions, conf *ffuf.Config) error {
if !foundkeyword {
errs.Add(fmt.Errorf("No FUZZ keyword(s) found in headers, URL or POST data, nothing to do"))
}
return errs.ErrorOrNil()
}

View file

@ -25,12 +25,15 @@ type Config struct {
Quiet bool
Colors bool
Wordlist string
OutputFile string
OutputFormat string
Delay optRange
Filters []FilterProvider
Matchers []FilterProvider
Threads int
Context context.Context
ProxyURL func(*http.Request) (*url.URL, error)
CommandLine string
}
func NewConfig(ctx context.Context) Config {

33
pkg/output/file_json.go Normal file
View file

@ -0,0 +1,33 @@
package output
import (
"encoding/json"
"io/ioutil"
"time"
"github.com/ffuf/ffuf/pkg/ffuf"
)
type jsonFileOutput struct {
CommandLine string `json:"commandline"`
Time string `json:"time"`
Results []Result `json:"results"`
}
func writeJSON(config *ffuf.Config, res []Result) error {
t := time.Now()
outJSON := jsonFileOutput{
CommandLine: config.CommandLine,
Time: t.Format(time.RFC3339),
Results: res,
}
outBytes, err := json.Marshal(outJSON)
if err != nil {
return err
}
err = ioutil.WriteFile(config.OutputFile, outBytes, 0644)
if err != nil {
return err
}
return nil
}

View file

@ -20,12 +20,21 @@ const (
)
type Stdoutput struct {
config *ffuf.Config
config *ffuf.Config
Results []Result
}
type Result struct {
Input string `json:"input"`
StatusCode int64 `json:"status"`
ContentLength int64 `json:"length"`
ContentWords int64 `json:"words"`
}
func NewStdoutput(conf *ffuf.Config) *Stdoutput {
var outp Stdoutput
outp.config = conf
outp.Results = []Result{}
return &outp
}
@ -52,6 +61,15 @@ func (s *Stdoutput) Error(errstring string) {
}
func (s *Stdoutput) Finalize() error {
var err error
if s.config.OutputFile != "" {
if s.config.OutputFormat == "json" {
err = writeJSON(s.config, s.Results)
}
if err != nil {
s.Error(fmt.Sprintf("%s", err))
}
}
fmt.Fprintf(os.Stderr, "\n")
return nil
}
@ -82,6 +100,16 @@ func (s *Stdoutput) Result(resp ffuf.Response) bool {
}
// Response survived the filtering, output the result
s.printResult(resp)
if s.config.OutputFile != "" {
// No need to store results if we're not going to use them later
sResult := Result{
Input: string(resp.Request.Input),
StatusCode: resp.StatusCode,
ContentLength: resp.ContentLength,
ContentWords: resp.ContentWords,
}
s.Results = append(s.Results, sResult)
}
return true
}