Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added hooks to standard output writer + misc #5736

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/nuclei/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.RuntimeMapVarP(&options.Vars, "var", "V", nil, "custom vars in key=value format"),
flagSet.StringVarP(&options.ResolversFile, "resolvers", "r", "", "file containing resolver list for nuclei"),
flagSet.BoolVarP(&options.SystemResolvers, "system-resolvers", "sr", false, "use system DNS resolving as error fallback"),
flagSet.BoolVarP(&options.DisableDefaultResolvers, "disable-default-resolvers", "dfr", false, "disable default resolvers"),
flagSet.BoolVarP(&options.DisableClustering, "disable-clustering", "dc", false, "disable clustering of requests"),
flagSet.BoolVar(&options.OfflineHTTP, "passive", false, "enable passive HTTP response processing mode"),
flagSet.BoolVarP(&options.ForceAttemptHTTP2, "force-http2", "fh2", false, "force http2 connection on requests"),
Expand Down
54 changes: 43 additions & 11 deletions pkg/output/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ type StandardWriter struct {
omitTemplate bool
DisableStdout bool
AddNewLinesOutputFile bool // by default this is only done for stdout
KeysToRedact []string
keysToRedact []*regexp.Regexp

RequestCallback func(templateID, url, requestType string, err error)
WriteCallback func(o *ResultEvent)
}

var decolorizerRegex = regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`)
Expand Down Expand Up @@ -265,8 +268,27 @@ func NewStandardWriter(options *types.Options) (*StandardWriter, error) {
storeResponse: options.StoreResponse,
storeResponseDir: options.StoreResponseDir,
omitTemplate: options.OmitTemplate,
KeysToRedact: options.Redact,
}
for _, key := range options.Redact {
keyPattern := regexp.MustCompile(fmt.Sprintf(`(?i)(%s\s*[:=]\s*["']?)[^"'\r\n&]+(["'\r\n]?)`, regexp.QuoteMeta(key)))
writer.keysToRedact = append(writer.keysToRedact, keyPattern)
}

return writer, nil
}

func NewStandardWriterWithHooks(
options *types.Options,
requestCallback func(templateID, url, requestType string, err error),
writeCallback func(o *ResultEvent),
) (*StandardWriter, error) {
writer, err := NewStandardWriter(options)
if err != nil {
return nil, err
}
writer.RequestCallback = requestCallback
writer.WriteCallback = writeCallback

return writer, nil
}

Expand All @@ -277,11 +299,12 @@ func (w *StandardWriter) Write(event *ResultEvent) error {
event.Template, event.TemplateURL = utils.TemplatePathURL(types.ToString(event.TemplatePath), types.ToString(event.TemplateID), event.TemplateVerifier)
}

if len(w.KeysToRedact) > 0 {
event.Request = redactKeys(event.Request, w.KeysToRedact)
event.Response = redactKeys(event.Response, w.KeysToRedact)
event.CURLCommand = redactKeys(event.CURLCommand, w.KeysToRedact)
event.Matched = redactKeys(event.Matched, w.KeysToRedact)
if len(w.keysToRedact) > 0 {
event.URL = w.redactKeys(event.URL)
event.Request = w.redactKeys(event.Request)
event.Response = w.redactKeys(event.Response)
event.CURLCommand = w.redactKeys(event.CURLCommand)
event.Matched = w.redactKeys(event.Matched)
}

event.Timestamp = time.Now()
Expand Down Expand Up @@ -319,12 +342,15 @@ func (w *StandardWriter) Write(event *ResultEvent) error {
_, _ = w.outputFile.Write([]byte("\n"))
}
}

if w.WriteCallback != nil {
w.WriteCallback(event)
}
return nil
}

func redactKeys(data string, keysToRedact []string) string {
for _, key := range keysToRedact {
keyPattern := regexp.MustCompile(fmt.Sprintf(`(?i)(%s\s*[:=]\s*["']?)[^"'\r\n&]+(["'\r\n]?)`, regexp.QuoteMeta(key)))
func (w *StandardWriter) redactKeys(data string) string {
for _, keyPattern := range w.keysToRedact {
data = keyPattern.ReplaceAllString(data, `$1***$2`)
}
return data
Expand All @@ -344,7 +370,11 @@ type JSONLogRequest struct {

// Request writes a log the requests trace log
func (w *StandardWriter) Request(templatePath, input, requestType string, requestErr error) {
if w.traceFile == nil && w.errorFile == nil {
if w.traceFile == nil && w.errorFile == nil && w.RequestCallback == nil {
return
}
if w.RequestCallback != nil {
w.RequestCallback(templatePath, input, requestType, requestErr)
return
}
request := &JSONLogRequest{
Expand Down Expand Up @@ -393,6 +423,7 @@ func (w *StandardWriter) Request(templatePath, input, requestType string, reques
if val := errkit.GetAttrValue(requestErr, "address"); val.Any() != nil {
request.Address = val.String()
}

data, err := jsoniter.Marshal(request)
if err != nil {
return
Expand All @@ -405,6 +436,7 @@ func (w *StandardWriter) Request(templatePath, input, requestType string, reques
if requestErr != nil && w.errorFile != nil {
_, _ = w.errorFile.Write(data)
}

}

// Colorizer returns the colorizer instance for writer
Expand Down
5 changes: 5 additions & 0 deletions pkg/protocols/common/protocolstate/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func Init(options *types.Options) error {

lfaAllowed = options.AllowLocalFileAccess
opts := fastdialer.DefaultOptions
if options.DisableDefaultResolvers {
opts.HostsFile = false
opts.ResolversFile = false
}
opts.DialerTimeout = options.GetTimeouts().DialTimeout
if options.DialerKeepAlive > 0 {
opts.DialerKeepAlive = options.DialerKeepAlive
Expand Down Expand Up @@ -134,6 +138,7 @@ func Init(options *types.Options) error {
if options.SystemResolvers {
opts.ResolversFile = true
opts.EnableFallback = true
opts.HostsFile = true
}
if len(options.InternalResolversList) > 0 {
opts.BaseResolvers = options.InternalResolversList
Expand Down
23 changes: 11 additions & 12 deletions pkg/testutils/testutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ type TemplateInfo struct {
func NewMockExecuterOptions(options *types.Options, info *TemplateInfo) *protocols.ExecutorOptions {
progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0)
executerOpts := &protocols.ExecutorOptions{
TemplateID: info.ID,
TemplateInfo: info.Info,
TemplatePath: info.Path,
Output: NewMockOutputWriter(options.OmitTemplate),
Options: options,
Progress: progressImpl,
ProjectFile: nil,
IssuesClient: nil,
Browser: nil,
Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory),
RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second),
TemplateID: info.ID,
TemplateInfo: info.Info,
TemplatePath: info.Path,
Output: NewMockOutputWriter(options.OmitTemplate),
Options: options,
Progress: progressImpl,
ProjectFile: nil,
IssuesClient: nil,
Browser: nil,
Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory),
RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second),
}
executerOpts.CreateTemplateCtxStore()
return executerOpts
Expand All @@ -116,7 +116,6 @@ type MockOutputWriter struct {
aurora aurora.Aurora
omitTemplate bool
RequestCallback func(templateID, url, requestType string, err error)
FailureCallback func(result *output.InternalEvent)
WriteCallback func(o *output.ResultEvent)
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ type Options struct {
UseInstalledChrome bool
// SystemResolvers enables override of nuclei's DNS client opting to use system resolver stack.
SystemResolvers bool
// DisableDNSResolvers disables default DNS resolvers for nuclei
DisableDefaultResolvers bool
// ShowActions displays a list of all headless actions
ShowActions bool
// Deprecated: Enabled by default through clistats . Metrics enables display of metrics via an http endpoint
Expand Down
Loading