mirror of
https://github.com/ffuf/ffuf
synced 2024-11-10 06:04:17 +00:00
Add -json option (#509)
* Add -json option Prints newline-delimited JSON output to STDOUT * sort * Clear terminal line via STDERR foreach JSON result For each JSON result being printed, prepend it with a TERMINAL_CLEAR_LINE via STDERR. This clears the progress line (which is also being emitted via STDERR) and leaves us with a clean stream of JSON lines in the terminal.
This commit is contained in:
parent
9aeae16a08
commit
4c1a75498b
8 changed files with 36 additions and 9 deletions
|
@ -4,6 +4,7 @@
|
|||
- Added response time logging and filtering
|
||||
- Added a CLI flag to specify TLS SNI value
|
||||
- Added full line colors
|
||||
- Added `-json` to emit newline delimited JSON output
|
||||
- Added 500 Internal Server Error to list of status codes matched by default
|
||||
- Changed
|
||||
- Fixed an issue where output file was created regardless of `-or`
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* [jimen0](https://github.com/jimen0)
|
||||
* [joohoi](https://github.com/joohoi)
|
||||
* [jsgv](https://github.com/jsgv)
|
||||
* [justinsteven](https://github.com/justinsteven)
|
||||
* [jvesiluoma](https://github.com/jvesiluoma)
|
||||
* [Kiblyn11](https://github.com/Kiblyn11)
|
||||
* [lc](https://github.com/lc)
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
stoponerrors = false
|
||||
threads = 40
|
||||
verbose = false
|
||||
json = false
|
||||
|
||||
[input]
|
||||
dirsearchcompat = false
|
||||
|
|
2
help.go
2
help.go
|
@ -61,7 +61,7 @@ func Usage() {
|
|||
Description: "",
|
||||
Flags: make([]UsageFlag, 0),
|
||||
Hidden: false,
|
||||
ExpectedFlags: []string{"ac", "acc", "c", "config", "maxtime", "maxtime-job", "noninteractive", "p", "rate", "s", "sa", "se", "sf", "t", "v", "V"},
|
||||
ExpectedFlags: []string{"ac", "acc", "c", "config", "json", "maxtime", "maxtime-job", "noninteractive", "p", "rate", "s", "sa", "se", "sf", "t", "v", "V"},
|
||||
}
|
||||
u_compat := UsageSection{
|
||||
Name: "COMPATIBILITY OPTIONS",
|
||||
|
|
1
main.go
1
main.go
|
@ -63,6 +63,7 @@ func ParseFlags(opts *ffuf.ConfigOptions) *ffuf.ConfigOptions {
|
|||
flag.BoolVar(&opts.Output.OutputSkipEmptyFile, "or", opts.Output.OutputSkipEmptyFile, "Don't create the output file if we don't have results")
|
||||
flag.BoolVar(&opts.General.AutoCalibration, "ac", opts.General.AutoCalibration, "Automatically calibrate filtering options")
|
||||
flag.BoolVar(&opts.General.Colors, "c", opts.General.Colors, "Colorize output.")
|
||||
flag.BoolVar(&opts.General.Json, "json", opts.General.Json, "JSON output, printing newline-delimited JSON records")
|
||||
flag.BoolVar(&opts.General.Noninteractive, "noninteractive", opts.General.Noninteractive, "Disable the interactive console functionality")
|
||||
flag.BoolVar(&opts.General.Quiet, "s", opts.General.Quiet, "Do not print additional information (silent mode)")
|
||||
flag.BoolVar(&opts.General.ShowVersion, "V", opts.General.ShowVersion, "Show version information.")
|
||||
|
|
|
@ -26,6 +26,7 @@ type Config struct {
|
|||
InputNum int `json:"cmd_inputnum"`
|
||||
InputProviders []InputProviderConfig `json:"inputproviders"`
|
||||
InputShell string `json:"inputshell"`
|
||||
Json bool `json:"json"`
|
||||
Matchers map[string]FilterProvider `json:"matchers"`
|
||||
MaxTime int `json:"maxtime"`
|
||||
MaxTimeJob int `json:"maxtime_job"`
|
||||
|
@ -79,6 +80,7 @@ func NewConfig(ctx context.Context, cancel context.CancelFunc) Config {
|
|||
conf.InputNum = 0
|
||||
conf.InputShell = ""
|
||||
conf.InputProviders = make([]InputProviderConfig, 0)
|
||||
conf.Json = false
|
||||
conf.Matchers = make(map[string]FilterProvider)
|
||||
conf.MaxTime = 0
|
||||
conf.MaxTimeJob = 0
|
||||
|
|
|
@ -49,6 +49,7 @@ type GeneralOptions struct {
|
|||
Colors bool
|
||||
ConfigFile string `toml:"-"`
|
||||
Delay string
|
||||
Json bool
|
||||
MaxTime int
|
||||
MaxTimeJob int
|
||||
Noninteractive bool
|
||||
|
@ -113,6 +114,7 @@ func NewConfigOptions() *ConfigOptions {
|
|||
c.General.AutoCalibration = false
|
||||
c.General.Colors = false
|
||||
c.General.Delay = ""
|
||||
c.General.Json = false
|
||||
c.General.MaxTime = 0
|
||||
c.General.MaxTimeJob = 0
|
||||
c.General.Noninteractive = false
|
||||
|
@ -449,6 +451,7 @@ func ConfigFromOptions(parseOpts *ConfigOptions, ctx context.Context, cancel con
|
|||
conf.MaxTimeJob = parseOpts.General.MaxTimeJob
|
||||
conf.Noninteractive = parseOpts.General.Noninteractive
|
||||
conf.Verbose = parseOpts.General.Verbose
|
||||
conf.Json = parseOpts.General.Json
|
||||
conf.Http2 = parseOpts.HTTP.Http2
|
||||
|
||||
// Handle copy as curl situation where POST method is implied by --data flag. If method is set to anything but GET, NOOP
|
||||
|
@ -483,6 +486,12 @@ func ConfigFromOptions(parseOpts *ConfigOptions, ctx context.Context, cancel con
|
|||
errs.Add(fmt.Errorf(errmsg))
|
||||
}
|
||||
}
|
||||
|
||||
// Make verbose mutually exclusive with json
|
||||
if parseOpts.General.Verbose && parseOpts.General.Json {
|
||||
errs.Add(fmt.Errorf("Cannot have -json and -v"))
|
||||
}
|
||||
|
||||
return &conf, errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package output
|
|||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -359,15 +360,16 @@ func (s *Stdoutput) writeResultToFile(resp ffuf.Response) string {
|
|||
}
|
||||
|
||||
func (s *Stdoutput) PrintResult(res ffuf.Result) {
|
||||
if s.config.Quiet {
|
||||
switch {
|
||||
case s.config.Quiet:
|
||||
s.resultQuiet(res)
|
||||
} else {
|
||||
if len(res.Input) > 1 || s.config.Verbose || len(s.config.OutputDirectory) > 0 {
|
||||
// Print a multi-line result (when using multiple input keywords and wordlists)
|
||||
s.resultMultiline(res)
|
||||
} else {
|
||||
s.resultNormal(res)
|
||||
}
|
||||
case s.config.Json:
|
||||
s.resultJson(res)
|
||||
case len(res.Input) > 1 || s.config.Verbose || len(s.config.OutputDirectory) > 0:
|
||||
// Print a multi-line result (when using multiple input keywords and wordlists)
|
||||
s.resultMultiline(res)
|
||||
default:
|
||||
s.resultNormal(res)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,6 +433,16 @@ func (s *Stdoutput) resultNormal(res ffuf.Result) {
|
|||
fmt.Println(resnormal)
|
||||
}
|
||||
|
||||
func (s *Stdoutput) resultJson(res ffuf.Result) {
|
||||
resBytes, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
s.Error(err.Error())
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, TERMINAL_CLEAR_LINE)
|
||||
fmt.Println(string(resBytes))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Stdoutput) colorize(status int64) string {
|
||||
if !s.config.Colors {
|
||||
return ""
|
||||
|
|
Loading…
Reference in a new issue