Support outputting all file formats concurrently (#218)
* Support outputting all file formats concurrently Previously ffuf would allow outputting to a single file-format, ie Markdown (md), json or HTML. It was not possible to output in multiple formats in the same execution. This change allows specifying an output (-of) of "all", which means that the output filename (-o) is used, but the appropriate suffix is added. As an example, ... -of all -o output/report Will output: - output/report.json - output/report.html - output/report.csv - ... etc Fixes ffuf/ffuf#215 Signed-off-by: Dave Walker (Daviey) <email@daviey.com> * Updated Changelog and added myself to CONTRIBUTORS Signed-off-by: Dave Walker (Daviey) <email@daviey.com> * Fix file extension for 'ecsv' when 'all' is used .. And fix CONTRIBUTORS.md to be alphabetical Signed-off-by: Dave Walker (Daviey) <email@daviey.com>
This commit is contained in:
parent
e4628ff481
commit
88720dfdc9
@ -6,6 +6,7 @@
|
|||||||
- Changed behaviour of `-maxtime`, can now be used for entire process.
|
- Changed behaviour of `-maxtime`, can now be used for entire process.
|
||||||
- A new flag `-ignore-body` so ffuf does not fetch the response content. Default value=false.
|
- A new flag `-ignore-body` so ffuf does not fetch the response content. Default value=false.
|
||||||
- Added the wordlists to the header information.
|
- Added the wordlists to the header information.
|
||||||
|
- Added support to output "all" formats (specify the path/filename sans file extension and ffuf will add the appropriate suffix for the filetype)
|
||||||
|
|
||||||
- Changed
|
- Changed
|
||||||
- Added tls renegotiation flag to fix #193 in http.Client
|
- Added tls renegotiation flag to fix #193 in http.Client
|
||||||
|
|||||||
4
main.go
4
main.go
@ -101,7 +101,7 @@ func main() {
|
|||||||
flag.StringVar(&opts.requestProto, "request-proto", "https", "Protocol to use along with raw request")
|
flag.StringVar(&opts.requestProto, "request-proto", "https", "Protocol to use along with raw request")
|
||||||
flag.StringVar(&conf.Method, "X", "GET", "HTTP method to use")
|
flag.StringVar(&conf.Method, "X", "GET", "HTTP method to use")
|
||||||
flag.StringVar(&conf.OutputFile, "o", "", "Write output to file")
|
flag.StringVar(&conf.OutputFile, "o", "", "Write output to file")
|
||||||
flag.StringVar(&opts.outputFormat, "of", "json", "Output file format. Available formats: json, ejson, html, md, csv, ecsv")
|
flag.StringVar(&opts.outputFormat, "of", "json", "Output file format. Available formats: json, ejson, html, md, csv, ecsv (or, 'all' for all formats)")
|
||||||
flag.StringVar(&conf.OutputDirectory, "od", "", "Directory path to store matched results to.")
|
flag.StringVar(&conf.OutputDirectory, "od", "", "Directory path to store matched results to.")
|
||||||
flag.BoolVar(&conf.IgnoreBody, "ignore-body", false, "Do not fetch the response content.")
|
flag.BoolVar(&conf.IgnoreBody, "ignore-body", false, "Do not fetch the response content.")
|
||||||
flag.BoolVar(&conf.Quiet, "s", false, "Do not print additional information (silent mode)")
|
flag.BoolVar(&conf.Quiet, "s", false, "Do not print additional information (silent mode)")
|
||||||
@ -430,7 +430,7 @@ func prepareConfig(parseOpts *cliOptions, conf *ffuf.Config) error {
|
|||||||
//Check the output file format option
|
//Check the output file format option
|
||||||
if conf.OutputFile != "" {
|
if conf.OutputFile != "" {
|
||||||
//No need to check / error out if output file isn't defined
|
//No need to check / error out if output file isn't defined
|
||||||
outputFormats := []string{"json", "ejson", "html", "md", "csv", "ecsv"}
|
outputFormats := []string{"all", "json", "ejson", "html", "md", "csv", "ecsv"}
|
||||||
found := false
|
found := false
|
||||||
for _, f := range outputFormats {
|
for _, f := range outputFormats {
|
||||||
if f == parseOpts.outputFormat {
|
if f == parseOpts.outputFormat {
|
||||||
|
|||||||
@ -83,7 +83,16 @@ func (s *Stdoutput) Banner() error {
|
|||||||
|
|
||||||
// Output file info
|
// Output file info
|
||||||
if len(s.config.OutputFile) > 0 {
|
if len(s.config.OutputFile) > 0 {
|
||||||
printOption([]byte("Output file"), []byte(s.config.OutputFile))
|
|
||||||
|
// Use filename as specified by user
|
||||||
|
OutputFile := s.config.OutputFile
|
||||||
|
|
||||||
|
if s.config.OutputFormat == "all" {
|
||||||
|
// Actually... append all extensions
|
||||||
|
OutputFile += ".{json,ejson,html,md,csv,ecsv}"
|
||||||
|
}
|
||||||
|
|
||||||
|
printOption([]byte("Output file"), []byte(OutputFile))
|
||||||
printOption([]byte("File format"), []byte(s.config.OutputFormat))
|
printOption([]byte("File format"), []byte(s.config.OutputFormat))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,10 +205,59 @@ func (s *Stdoutput) Warning(warnstring string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Stdoutput) writeToAll(config *ffuf.Config, res []Result) error {
|
||||||
|
var err error
|
||||||
|
var BaseFilename string = s.config.OutputFile
|
||||||
|
|
||||||
|
// Go through each type of write, adding
|
||||||
|
// the suffix to each output file.
|
||||||
|
|
||||||
|
s.config.OutputFile = BaseFilename + ".json"
|
||||||
|
err = writeJSON(s.config, s.Results)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(fmt.Sprintf("%s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
s.config.OutputFile = BaseFilename + ".ejson"
|
||||||
|
err = writeEJSON(s.config, s.Results)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(fmt.Sprintf("%s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
s.config.OutputFile = BaseFilename + ".html"
|
||||||
|
err = writeHTML(s.config, s.Results)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(fmt.Sprintf("%s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
s.config.OutputFile = BaseFilename + ".md"
|
||||||
|
err = writeMarkdown(s.config, s.Results)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(fmt.Sprintf("%s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
s.config.OutputFile = BaseFilename + ".csv"
|
||||||
|
err = writeCSV(s.config, s.Results, false)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(fmt.Sprintf("%s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
s.config.OutputFile = BaseFilename + ".ecsv"
|
||||||
|
err = writeCSV(s.config, s.Results, true)
|
||||||
|
if err != nil {
|
||||||
|
s.Error(fmt.Sprintf("%s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Stdoutput) Finalize() error {
|
func (s *Stdoutput) Finalize() error {
|
||||||
var err error
|
var err error
|
||||||
if s.config.OutputFile != "" {
|
if s.config.OutputFile != "" {
|
||||||
if s.config.OutputFormat == "json" {
|
if s.config.OutputFormat == "all" {
|
||||||
|
err = s.writeToAll(s.config, s.Results)
|
||||||
|
} else if s.config.OutputFormat == "json" {
|
||||||
err = writeJSON(s.config, s.Results)
|
err = writeJSON(s.config, s.Results)
|
||||||
} else if s.config.OutputFormat == "ejson" {
|
} else if s.config.OutputFormat == "ejson" {
|
||||||
err = writeEJSON(s.config, s.Results)
|
err = writeEJSON(s.config, s.Results)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user