diff --git a/v2/cmd/integration-test/code.go b/v2/cmd/integration-test/code.go index eb7fb03c7..c6dd5f4f9 100644 --- a/v2/cmd/integration-test/code.go +++ b/v2/cmd/integration-test/code.go @@ -69,7 +69,10 @@ func executeNucleiAsCode(templatePath, templateURL string) ([]string, error) { defer cache.Close() mockProgress := &testutils.MockProgressClient{} - reportingClient, _ := reporting.New(&reporting.Options{}, "") + reportingClient, err := reporting.New(&reporting.Options{}, "") + if err != nil { + return nil, err + } defer reportingClient.Close() outputWriter := testutils.NewMockOutputWriter() diff --git a/v2/cmd/integration-test/http.go b/v2/cmd/integration-test/http.go index bd4dee057..0ac66a0fe 100644 --- a/v2/cmd/integration-test/http.go +++ b/v2/cmd/integration-test/http.go @@ -8,7 +8,6 @@ import ( "net/http/httptest" "net/http/httputil" "os" - "path/filepath" "reflect" "strconv" "strings" @@ -833,13 +832,16 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error { defer server.Close() // create temp file - FileLoc := filepath.Join(os.TempDir(), "httpselfcontained.yaml") - err := os.WriteFile(FileLoc, []byte("one\ntwo\n"), 0600) + FileLoc, err := os.CreateTemp("", "self-contained-payload-*.txt") if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to create temporary file").WithTag(filePath) + return errorutil.NewWithErr(err).Msgf("failed to create temp file") } + if _, err := FileLoc.Write([]byte("one\ntwo\n")); err != nil { + return errorutil.NewWithErr(err).Msgf("failed to write payload to temp file") + } + defer FileLoc.Close() - results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name()) if err != nil { return err } diff --git a/v2/cmd/integration-test/template-dir.go b/v2/cmd/integration-test/template-dir.go index 025fbb296..8b318ad89 100644 --- a/v2/cmd/integration-test/template-dir.go +++ b/v2/cmd/integration-test/template-dir.go @@ -4,13 +4,9 @@ import ( "os" "github.com/projectdiscovery/nuclei/v2/pkg/testutils" + errorutil "github.com/projectdiscovery/utils/errors" ) -func getTemplatesDir() string { - temp := os.TempDir() - return temp -} - var templatesDirTestCases = map[string]testutils.TestCase{ "dns/cname-fingerprint.yaml": &templateDirWithTargetTest{}, } @@ -19,9 +15,13 @@ type templateDirWithTargetTest struct{} // Execute executes a test case and returns an error if occurred func (h *templateDirWithTargetTest) Execute(filePath string) error { - defer os.RemoveAll(getTemplatesDir()) + tempdir, err := os.MkdirTemp("", "nuclei-update-dir-*") + if err != nil { + return errorutil.NewWithErr(err).Msgf("failed to create temp dir") + } + defer os.RemoveAll(tempdir) - results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "8x8exch02.8x8.com", debug, "-ud", getTemplatesDir()) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "8x8exch02.8x8.com", debug, "-ud", tempdir) if err != nil { return err } diff --git a/v2/cmd/nuclei/main.go b/v2/cmd/nuclei/main.go index 902511d75..0e16d197a 100644 --- a/v2/cmd/nuclei/main.go +++ b/v2/cmd/nuclei/main.go @@ -23,6 +23,7 @@ import ( "github.com/projectdiscovery/nuclei/v2/pkg/protocols/http" templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types" "github.com/projectdiscovery/nuclei/v2/pkg/types" + "github.com/projectdiscovery/nuclei/v2/pkg/types/scanstrategy" "github.com/projectdiscovery/nuclei/v2/pkg/utils/monitor" errorutil "github.com/projectdiscovery/utils/errors" fileutil "github.com/projectdiscovery/utils/file" @@ -243,7 +244,6 @@ on extensive configurability, massive extensibility and ease of use.`) flagSet.IntVarP(&options.HeadlessBulkSize, "headless-bulk-size", "hbs", 10, "maximum number of headless hosts to be analyzed in parallel per template"), flagSet.IntVarP(&options.HeadlessTemplateThreads, "headless-concurrency", "headc", 10, "maximum number of headless templates to be executed in parallel"), ) - flagSet.CreateGroup("optimization", "Optimizations", flagSet.IntVar(&options.Timeout, "timeout", 10, "time to wait in seconds before timeout"), flagSet.IntVar(&options.Retries, "retries", 1, "number of times to retry a failed request"), @@ -256,9 +256,9 @@ on extensive configurability, massive extensibility and ease of use.`) flagSet.BoolVarP(&options.StopAtFirstMatch, "stop-at-first-match", "spm", false, "stop processing HTTP requests after the first match (may break template/workflow logic)"), flagSet.BoolVar(&options.Stream, "stream", false, "stream mode - start elaborating without sorting the input"), flagSet.EnumVarP(&options.ScanStrategy, "scan-strategy", "ss", goflags.EnumVariable(0), "strategy to use while scanning(auto/host-spray/template-spray)", goflags.AllowdTypes{ - "auto": goflags.EnumVariable(0), - "host-spray": goflags.EnumVariable(1), - "template-spray": goflags.EnumVariable(2), + scanstrategy.Auto.String(): goflags.EnumVariable(0), + scanstrategy.HostSpray.String(): goflags.EnumVariable(1), + scanstrategy.TemplateSpray.String(): goflags.EnumVariable(2), }), flagSet.DurationVarP(&options.InputReadTimeout, "input-read-timeout", "irt", time.Duration(3*time.Minute), "timeout on input read"), flagSet.BoolVarP(&options.DisableHTTPProbe, "no-httpx", "nh", false, "disable httpx probing for non-url input"), diff --git a/v2/internal/runner/options.go b/v2/internal/runner/options.go index cf7e1f3a5..c1603a47f 100644 --- a/v2/internal/runner/options.go +++ b/v2/internal/runner/options.go @@ -22,7 +22,6 @@ import ( "github.com/projectdiscovery/nuclei/v2/pkg/types" "github.com/projectdiscovery/stringsutil" fileutil "github.com/projectdiscovery/utils/file" - logutil "github.com/projectdiscovery/utils/log" ) func ConfigureOptions() error { @@ -251,7 +250,7 @@ func configureOutput(options *types.Options) { } // disable standard logger (ref: https://github.com/golang/go/issues/19895) - logutil.DisableDefaultLogger() + // logutil.DisableDefaultLogger() } // loadResolvers loads resolvers from both user provided flag and file diff --git a/v2/pkg/core/execute_options.go b/v2/pkg/core/execute_options.go index e9d87c885..97bff350b 100644 --- a/v2/pkg/core/execute_options.go +++ b/v2/pkg/core/execute_options.go @@ -10,6 +10,7 @@ import ( "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs" "github.com/projectdiscovery/nuclei/v2/pkg/templates" "github.com/projectdiscovery/nuclei/v2/pkg/templates/types" + "github.com/projectdiscovery/nuclei/v2/pkg/types/scanstrategy" stringsutil "github.com/projectdiscovery/utils/strings" ) @@ -40,10 +41,10 @@ func (e *Engine) ExecuteScanWithOpts(templatesList []*templates.Template, target finalTemplates = templatesList } - if stringsutil.EqualFoldAny(e.options.ScanStrategy, "auto", "") { + if stringsutil.EqualFoldAny(e.options.ScanStrategy, scanstrategy.Auto.String(), "") { // TODO: this is only a placeholder, auto scan strategy should choose scan strategy // based on no of hosts , templates , stream and other optimization parameters - e.options.ScanStrategy = "template-spray" + e.options.ScanStrategy = scanstrategy.TemplateSpray.String() } filtered := []*templates.Template{} @@ -60,11 +61,11 @@ func (e *Engine) ExecuteScanWithOpts(templatesList []*templates.Template, target // Execute All SelfContained in parallel e.executeAllSelfContained(selfContained, results, selfcontainedWg) - var strategyResult *atomic.Bool + strategyResult := &atomic.Bool{} switch e.options.ScanStrategy { - case "template-spray": + case scanstrategy.TemplateSpray.String(): strategyResult = e.executeTemplateSpray(filtered, target) - case "host-spray": + case scanstrategy.TemplateSpray.String(): strategyResult = e.executeHostSpray(filtered, target) } diff --git a/v2/pkg/testutils/integration.go b/v2/pkg/testutils/integration.go index 5968e44b1..bf973dfa4 100644 --- a/v2/pkg/testutils/integration.go +++ b/v2/pkg/testutils/integration.go @@ -50,6 +50,8 @@ func RunNucleiBareArgsAndGetResults(debug bool, extra ...string) ([]string, erro extra = append(extra, ExtraDebugArgs...) cmd.Args = append(cmd.Args, extra...) cmd.Args = append(cmd.Args, "-duc") // disable auto updates + cmd.Args = append(cmd.Args, "-interactions-poll-duration", "1") + cmd.Args = append(cmd.Args, "-interactions-cooldown-period", "10") if debug { cmd.Args = append(cmd.Args, "-debug") cmd.Stderr = os.Stderr @@ -98,6 +100,7 @@ func RunNucleiBinaryAndGetLoadedTemplates(nucleiBinary string, debug bool, args return matches[0][1], nil } func RunNucleiBinaryAndGetCombinedOutput(debug bool, args []string) (string, error) { + args = append(args, "-interactions-cooldown-period", "10", "-interactions-poll-duration", "1") cmd := exec.Command("./nuclei", args...) if debug { cmd.Args = append(cmd.Args, "-debug") diff --git a/v2/pkg/types/scanstrategy/scan_strategy.go b/v2/pkg/types/scanstrategy/scan_strategy.go new file mode 100644 index 000000000..c8c893110 --- /dev/null +++ b/v2/pkg/types/scanstrategy/scan_strategy.go @@ -0,0 +1,28 @@ +package scanstrategy + +import ( + mapsutil "github.com/projectdiscovery/utils/maps" +) + +// ScanStrategy supported +type ScanStrategy uint8 + +const ( + Auto ScanStrategy = iota + HostSpray + TemplateSpray +) + +var strategies mapsutil.Map[ScanStrategy, string] + +func init() { + strategies = make(mapsutil.Map[ScanStrategy, string]) + strategies[Auto] = "auto" + strategies[HostSpray] = "host-spray" + strategies[TemplateSpray] = "template-spray" +} + +// String representation of the scan strategy +func (s ScanStrategy) String() string { + return strategies[s] +}