diff --git a/v2/cmd/functional-test/main.go b/v2/cmd/functional-test/main.go index bc95f20b..fc96fde8 100644 --- a/v2/cmd/functional-test/main.go +++ b/v2/cmd/functional-test/main.go @@ -15,6 +15,7 @@ import ( ) var ( + debug = os.Getenv("DEBUG") == "true" success = aurora.Green("[✓]").String() failed = aurora.Red("[✘]").String() errored = false @@ -65,11 +66,11 @@ func runIndividualTestCase(testcase string) error { if len(parts) > 1 { finalArgs = parts[1:] } - mainOutput, err := testutils.RunNucleiBinaryAndGetLoadedTemplates(*mainNucleiBinary, finalArgs) + mainOutput, err := testutils.RunNucleiBinaryAndGetLoadedTemplates(*mainNucleiBinary, debug, finalArgs) if err != nil { return errors.Wrap(err, "could not run nuclei main test") } - devOutput, err := testutils.RunNucleiBinaryAndGetLoadedTemplates(*devNucleiBinary, finalArgs) + devOutput, err := testutils.RunNucleiBinaryAndGetLoadedTemplates(*devNucleiBinary, debug, finalArgs) if err != nil { return errors.Wrap(err, "could not run nuclei dev test") } diff --git a/v2/cmd/integration-test/dns.go b/v2/cmd/integration-test/dns.go index 7661f48f..3e1ae814 100644 --- a/v2/cmd/integration-test/dns.go +++ b/v2/cmd/integration-test/dns.go @@ -14,7 +14,7 @@ type dnsBasic struct{} func (h *dnsBasic) Execute(filePath string) error { var routerErr error - results, err := testutils.RunNucleiAndGetResults(filePath, "one.one.one.one", debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "one.one.one.one", debug) if err != nil { return err } diff --git a/v2/cmd/integration-test/http.go b/v2/cmd/integration-test/http.go index 8188c27a..6d43c0cc 100644 --- a/v2/cmd/integration-test/http.go +++ b/v2/cmd/integration-test/http.go @@ -47,16 +47,16 @@ type httpGetHeaders struct{} // Execute executes a test case and returns an error if occurred func (h *httpGetHeaders) Execute(filePath string) error { router := httprouter.New() - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if strings.EqualFold(r.Header.Get("test"), "nuclei") { fmt.Fprintf(w, "This is test headers matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -71,16 +71,16 @@ type httpGetQueryString struct{} // Execute executes a test case and returns an error if occurred func (h *httpGetQueryString) Execute(filePath string) error { router := httprouter.New() - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if strings.EqualFold(r.URL.Query().Get("test"), "nuclei") { fmt.Fprintf(w, "This is test querystring matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -95,18 +95,18 @@ type httpGetRedirects struct{} // Execute executes a test case and returns an error if occurred func (h *httpGetRedirects) Execute(filePath string) error { router := httprouter.New() - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) http.Redirect(w, r, "/redirected", http.StatusFound) - })) - router.GET("/redirected", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + }) + router.GET("/redirected", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) fmt.Fprintf(w, "This is test redirects matcher text") - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -121,14 +121,14 @@ type httpGet struct{} // Execute executes a test case and returns an error if occurred func (h *httpGet) Execute(filePath string) error { router := httprouter.New() - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) fmt.Fprintf(w, "This is test matcher text") - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -145,7 +145,7 @@ func (h *httpPostBody) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.POST("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if err := r.ParseForm(); err != nil { routerErr = err @@ -154,11 +154,11 @@ func (h *httpPostBody) Execute(filePath string) error { if strings.EqualFold(r.Form.Get("username"), "test") && strings.EqualFold(r.Form.Get("password"), "nuclei") { fmt.Fprintf(w, "This is test post-body matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -178,7 +178,7 @@ func (h *httpPostJSONBody) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.POST("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) type doc struct { @@ -193,11 +193,11 @@ func (h *httpPostJSONBody) Execute(filePath string) error { if strings.EqualFold(obj.Username, "test") && strings.EqualFold(obj.Password, "nuclei") { fmt.Fprintf(w, "This is test post-json-body matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -217,7 +217,7 @@ func (h *httpPostMultipartBody) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.POST("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if err := r.ParseMultipartForm(1 * 1024); err != nil { routerErr = err @@ -236,11 +236,11 @@ func (h *httpPostMultipartBody) Execute(filePath string) error { if strings.EqualFold(password[0], "nuclei") && strings.EqualFold(file[0].Filename, "username") { fmt.Fprintf(w, "This is test post-multipart matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -260,7 +260,7 @@ func (h *httpRawDynamicExtractor) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.POST("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if err := r.ParseForm(); err != nil { routerErr = err @@ -269,17 +269,17 @@ func (h *httpRawDynamicExtractor) Execute(filePath string) error { if strings.EqualFold(r.Form.Get("testing"), "parameter") { fmt.Fprintf(w, "Token: 'nuclei'") } - })) - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + }) + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if strings.EqualFold(r.URL.Query().Get("username"), "nuclei") { fmt.Fprintf(w, "Test is test-dynamic-extractor-raw matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -299,16 +299,16 @@ func (h *httpRawGetQuery) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if strings.EqualFold(r.URL.Query().Get("test"), "nuclei") { fmt.Fprintf(w, "Test is test raw-get-query-matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -328,15 +328,15 @@ func (h *httpRawGet) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) fmt.Fprintf(w, "Test is test raw-get-matcher text") - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -356,7 +356,7 @@ func (h *httpRawPayload) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.POST("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if err := r.ParseForm(); err != nil { routerErr = err @@ -368,11 +368,11 @@ func (h *httpRawPayload) Execute(filePath string) error { if strings.EqualFold(r.Form.Get("username"), "test") && (strings.EqualFold(r.Form.Get("password"), "nuclei") || strings.EqualFold(r.Form.Get("password"), "guest")) { fmt.Fprintf(w, "Test is raw-payload matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -392,7 +392,7 @@ func (h *httpRawPostBody) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.POST("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if err := r.ParseForm(); err != nil { routerErr = err @@ -401,11 +401,11 @@ func (h *httpRawPostBody) Execute(filePath string) error { if strings.EqualFold(r.Form.Get("username"), "test") && strings.EqualFold(r.Form.Get("password"), "nuclei") { fmt.Fprintf(w, "Test is test raw-post-body-matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -425,7 +425,7 @@ func (h *httpRawCookieReuse) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.POST("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if err := r.ParseForm(); err != nil { routerErr = err @@ -434,8 +434,8 @@ func (h *httpRawCookieReuse) Execute(filePath string) error { if strings.EqualFold(r.Form.Get("testing"), "parameter") { http.SetCookie(w, &http.Cookie{Name: "nuclei", Value: "test"}) } - })) - router.GET("/", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + }) + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) if err := r.ParseForm(); err != nil { routerErr = err @@ -450,11 +450,11 @@ func (h *httpRawCookieReuse) Execute(filePath string) error { if strings.EqualFold(cookie.Value, "test") { fmt.Fprintf(w, "Test is test-cookie-reuse matcher text") } - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -479,7 +479,7 @@ func (h *httpRawUnsafeRequest) Execute(filePath string) error { }) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, "http://"+ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "http://"+ts.URL, debug) if err != nil { return err } @@ -499,18 +499,18 @@ func (h *httpRequestCondition) Execute(filePath string) error { router := httprouter.New() var routerErr error - router.GET("/200", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + router.GET("/200", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) w.WriteHeader(200) - })) - router.GET("/400", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + }) + router.GET("/400", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { httpDebugRequestDump(r) w.WriteHeader(400) - })) + }) ts := httptest.NewServer(router) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } diff --git a/v2/cmd/integration-test/network.go b/v2/cmd/integration-test/network.go index 5bb0fe51..a377a1c0 100644 --- a/v2/cmd/integration-test/network.go +++ b/v2/cmd/integration-test/network.go @@ -32,7 +32,7 @@ func (h *networkBasic) Execute(filePath string) error { }) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } @@ -75,7 +75,7 @@ func (h *networkMultiStep) Execute(filePath string) error { }) defer ts.Close() - results, err := testutils.RunNucleiAndGetResults(filePath, ts.URL, debug) + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { return err } diff --git a/v2/cmd/nuclei/main.go b/v2/cmd/nuclei/main.go index cae40155..e40a6dad 100644 --- a/v2/cmd/nuclei/main.go +++ b/v2/cmd/nuclei/main.go @@ -188,3 +188,10 @@ func createGroup(flagSet *goflags.FlagSet, groupName, description string, flags currentFlag.Group(groupName) } } + +/* +HacktoberFest update: Below, you can find our ticket recommendations. Tasks with the "good first issue" label are suitable for first time contributors. If you have other ideas, or need help with getting started, join our Discord channel or reach out to @forgedhallpass. + +https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aprojectdiscovery+label%3AHacktoberfest + +*/ diff --git a/v2/internal/testutils/integration.go b/v2/internal/testutils/integration.go index bb5d557f..f2c39886 100644 --- a/v2/internal/testutils/integration.go +++ b/v2/internal/testutils/integration.go @@ -2,6 +2,7 @@ package testutils import ( "errors" + "fmt" "net" "os" "os/exec" @@ -9,20 +10,36 @@ import ( "strings" ) -// RunNucleiAndGetResults returns a list of results for a template -func RunNucleiAndGetResults(template, url string, debug bool, extra ...string) ([]string, error) { - cmd := exec.Command("./nuclei", "-t", template, "-target", url, "-silent") +// RunNucleiTemplateAndGetResults returns a list of results for a template +func RunNucleiTemplateAndGetResults(template, url string, debug bool, extra ...string) ([]string, error) { + return runNucleiAndGetResults(true, template, url, debug, extra...) +} + +// RunNucleiWorkflowAndGetResults returns a list of results for a workflow +func RunNucleiWorkflowAndGetResults(template, url string, debug bool, extra ...string) ([]string, error) { + return runNucleiAndGetResults(false, template, url, debug, extra...) +} + +func runNucleiAndGetResults(isTemplate bool, template, url string, debug bool, extra ...string) ([]string, error) { + var templateOrWorkflowFlag string + if isTemplate { + templateOrWorkflowFlag = "-t" + } else { + templateOrWorkflowFlag = "-w" + } + + cmd := exec.Command("./nuclei", templateOrWorkflowFlag, template, "-target", url, "-silent") if debug { - cmd = exec.Command("./nuclei", "-t", template, "-target", url, "-debug") + cmd = exec.Command("./nuclei", templateOrWorkflowFlag, template, "-target", url, "-debug") cmd.Stderr = os.Stderr + fmt.Println(cmd.String()) } cmd.Args = append(cmd.Args, extra...) - data, err := cmd.Output() if err != nil { return nil, err } - parts := []string{} + var parts []string items := strings.Split(string(data), "\n") for _, i := range items { if i != "" { @@ -35,9 +52,11 @@ func RunNucleiAndGetResults(template, url string, debug bool, extra ...string) ( var templateLoaded = regexp.MustCompile(`(?:Templates|Workflows) loaded[^:]*: (\d+)`) // RunNucleiBinaryAndGetLoadedTemplates returns a list of results for a template -func RunNucleiBinaryAndGetLoadedTemplates(nucleiBinary string, args []string) (string, error) { +func RunNucleiBinaryAndGetLoadedTemplates(nucleiBinary string, debug bool, args []string) (string, error) { cmd := exec.Command(nucleiBinary, args...) - + if debug { + fmt.Println(cmd.String()) + } data, err := cmd.CombinedOutput() if err != nil { return "", err @@ -49,29 +68,6 @@ func RunNucleiBinaryAndGetLoadedTemplates(nucleiBinary string, args []string) (s return matches[0][1], nil } -// RunNucleiWorkflowAndGetResults returns a list of results for a workflow -func RunNucleiWorkflowAndGetResults(template, url string, debug bool, extra ...string) ([]string, error) { - cmd := exec.Command("./nuclei", "-w", template, "-target", url, "-silent") - if debug { - cmd = exec.Command("./nuclei", "-w", template, "-target", url, "-debug") - cmd.Stderr = os.Stderr - } - cmd.Args = append(cmd.Args, extra...) - - data, err := cmd.Output() - if err != nil { - return nil, err - } - parts := []string{} - items := strings.Split(string(data), "\n") - for _, i := range items { - if i != "" { - parts = append(parts, i) - } - } - return parts, nil -} - // TestCase is a single integration test case type TestCase interface { // Execute executes a test case and returns any errors if occurred