mirror of https://github.com/daffainfo/nuclei.git
Merge remote-tracking branch 'origin/dev' into colorize_responses
commit
742a5c44fc
|
@ -1,8 +1,10 @@
|
|||
name: 🌥 Docker Push
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_run:
|
||||
workflows: ["🎉 Release Binary"]
|
||||
types:
|
||||
- completed
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
FROM golang:1.17.1-alpine as build-env
|
||||
RUN GO111MODULE=on go get -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei
|
||||
RUN go install -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest
|
||||
|
||||
FROM alpine:3.14
|
||||
RUN apk add --no-cache bind-tools ca-certificates
|
||||
RUN apk add --no-cache bind-tools ca-certificates chromium
|
||||
COPY --from=build-env /go/bin/nuclei /usr/local/bin/nuclei
|
||||
ENTRYPOINT ["nuclei"]
|
||||
|
|
|
@ -129,7 +129,7 @@ CONFIGURATIONS:
|
|||
|
||||
INTERACTSH:
|
||||
-no-interactsh disable interactsh server for OOB testing
|
||||
-interactsh-url string interactsh server url for self-hosted instance (default "https://interact.sh")
|
||||
-interactsh-url string interactsh server url for self-hosted instance (default "https://interactsh.com")
|
||||
-interactsh-token string authentication token for self-hosted interactsh server
|
||||
-interactions-cache-size int number of requests to keep in the interactions cache (default 5000)
|
||||
-interactions-eviction int number of seconds to wait before evicting requests from cache (default 60)
|
||||
|
|
|
@ -2026,6 +2026,19 @@ Recursion determines if resolver should recurse all records to get fresh results
|
|||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>resolvers</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Resolvers to use for the dns requests
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -373,6 +373,14 @@
|
|||
"type": "boolean",
|
||||
"title": "recurse all servers",
|
||||
"description": "Recursion determines if resolver should recurse all records to get fresh results"
|
||||
},
|
||||
"resolvers": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Resolvers",
|
||||
"description": "Define resolvers to use within the template"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
|||
|
||||
createGroup(flagSet, "interactsh", "interactsh",
|
||||
flagSet.BoolVar(&options.NoInteractsh, "no-interactsh", false, "disable interactsh server for OOB testing"),
|
||||
flagSet.StringVar(&options.InteractshURL, "interactsh-url", "https://interact.sh", "interactsh server url for self-hosted instance"),
|
||||
flagSet.StringVar(&options.InteractshURL, "interactsh-url", "https://interactsh.com", "interactsh server url for self-hosted instance"),
|
||||
flagSet.StringVar(&options.InteractshToken, "interactsh-token", "", "authentication token for self-hosted interactsh server"),
|
||||
flagSet.IntVar(&options.InteractionsCacheSize, "interactions-cache-size", 5000, "number of requests to keep in the interactions cache"),
|
||||
flagSet.IntVar(&options.InteractionsEviction, "interactions-eviction", 60, "number of seconds to wait before evicting requests from cache"),
|
||||
|
@ -139,6 +139,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
|||
flagSet.BoolVar(&options.Headless, "headless", false, "enable templates that require headless browser support"),
|
||||
flagSet.IntVar(&options.PageTimeout, "page-timeout", 20, "seconds to wait for each page in headless mode"),
|
||||
flagSet.BoolVar(&options.ShowBrowser, "show-browser", false, "show the browser on the screen when running templates with headless mode"),
|
||||
flagSet.BoolVar(&options.UseInstalledChrome, "system-chrome", false, "Use local installed chrome browser instead of nuclei installed"),
|
||||
)
|
||||
|
||||
createGroup(flagSet, "debug", "Debug",
|
||||
|
@ -188,3 +189,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
|
||||
|
||||
*/
|
||||
|
|
|
@ -95,6 +95,7 @@ func validateOptions(options *types.Options) error {
|
|||
}
|
||||
|
||||
if options.Validate {
|
||||
options.Headless = true // required for correct validation of headless templates
|
||||
validateTemplatePaths(options.TemplatesDirectory, options.Templates, options.Workflows)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -256,7 +256,7 @@ func (c *Client) RequestEvent(interactshURL string, data *RequestData) {
|
|||
// HasMatchers returns true if an operator has interactsh part
|
||||
// matchers or extractors.
|
||||
//
|
||||
// Used by requests to show result or not depending on presence of interact.sh
|
||||
// Used by requests to show result or not depending on presence of interactsh.com
|
||||
// data part matchers.
|
||||
func HasMatchers(op *operators.Operators) bool {
|
||||
if op == nil {
|
||||
|
|
|
@ -72,6 +72,8 @@ type Request struct {
|
|||
// description: |
|
||||
// Recursion determines if resolver should recurse all records to get fresh results.
|
||||
Recursion bool `yaml:"recursion,omitempty" jsonschema:"title=recurse all servers,description=Recursion determines if resolver should recurse all records to get fresh results"`
|
||||
// Resolvers to use for the dns requests
|
||||
Resolvers []string `yaml:"resolvers,omitempty" jsonschema:"title=Resolvers,description=Define resolvers to use within the template"`
|
||||
}
|
||||
|
||||
func (request *Request) GetCompiledOperators() []*operators.Operators {
|
||||
|
@ -85,10 +87,14 @@ func (request *Request) GetID() string {
|
|||
|
||||
// Compile compiles the protocol request for further execution.
|
||||
func (request *Request) Compile(options *protocols.ExecuterOptions) error {
|
||||
// Create a dns client for the class
|
||||
client, err := dnsclientpool.Get(options.Options, &dnsclientpool.Configuration{
|
||||
dnsClientOptions := &dnsclientpool.Configuration{
|
||||
Retries: request.Retries,
|
||||
})
|
||||
}
|
||||
if len(request.Resolvers) > 0 {
|
||||
dnsClientOptions.Resolvers = request.Resolvers
|
||||
}
|
||||
// Create a dns client for the class
|
||||
client, err := dnsclientpool.Get(options.Options, dnsClientOptions)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get dns client")
|
||||
}
|
||||
|
|
|
@ -44,21 +44,24 @@ func Init(options *types.Options) error {
|
|||
type Configuration struct {
|
||||
// Retries contains the retries for the dns client
|
||||
Retries int
|
||||
// Resolvers contains the specific per request resolvers
|
||||
Resolvers []string
|
||||
}
|
||||
|
||||
// Hash returns the hash of the configuration to allow client pooling
|
||||
func (c *Configuration) Hash() string {
|
||||
builder := &strings.Builder{}
|
||||
builder.Grow(8)
|
||||
builder.WriteString("r")
|
||||
builder.WriteString(strconv.Itoa(c.Retries))
|
||||
builder.WriteString("l")
|
||||
builder.WriteString(strings.Join(c.Resolvers, ""))
|
||||
hash := builder.String()
|
||||
return hash
|
||||
}
|
||||
|
||||
// Get creates or gets a client for the protocol based on custom configuration
|
||||
func Get(options *types.Options, configuration *Configuration) (*retryabledns.Client, error) {
|
||||
if !(configuration.Retries > 1) {
|
||||
if !(configuration.Retries > 1) && len(configuration.Resolvers) == 0 {
|
||||
return normalClient, nil
|
||||
}
|
||||
hash := configuration.Hash()
|
||||
|
@ -72,6 +75,8 @@ func Get(options *types.Options, configuration *Configuration) (*retryabledns.Cl
|
|||
resolvers := defaultResolvers
|
||||
if options.ResolversFile != "" {
|
||||
resolvers = options.InternalResolversList
|
||||
} else if len(configuration.Resolvers) > 0 {
|
||||
resolvers = configuration.Resolvers
|
||||
}
|
||||
client := retryabledns.New(resolvers, configuration.Retries)
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ func New(options *types.Options) (*Browser, error) {
|
|||
return nil, errors.Wrap(err, "could not create temporary directory")
|
||||
}
|
||||
previouspids := findChromeProcesses()
|
||||
|
||||
chromeLauncher := launcher.New().
|
||||
Leakless(false).
|
||||
Set("disable-gpu", "true").
|
||||
|
@ -49,6 +50,14 @@ func New(options *types.Options) (*Browser, error) {
|
|||
Delete("use-mock-keychain").
|
||||
UserDataDir(dataStore)
|
||||
|
||||
if options.UseInstalledChrome {
|
||||
if chromePath, hasChrome := launcher.LookPath(); hasChrome {
|
||||
chromeLauncher.Bin(chromePath)
|
||||
} else {
|
||||
return nil, errors.New("the chrome browser is not installed")
|
||||
}
|
||||
}
|
||||
|
||||
if options.ShowBrowser {
|
||||
chromeLauncher = chromeLauncher.Headless(false)
|
||||
} else {
|
||||
|
|
|
@ -110,9 +110,9 @@ func Parse(request, baseURL string, unsafe bool) (*Request, error) {
|
|||
}
|
||||
rawRequest.FullURL = fmt.Sprintf("%s://%s%s", parsedURL.Scheme, strings.TrimSpace(hostURL), rawRequest.Path)
|
||||
|
||||
// If raw request doesn't have a Host header
|
||||
// this will be generated from the parsed baseURL
|
||||
if rawRequest.Headers["Host"] == "" {
|
||||
// If raw request doesn't have a Host header and isn't marked unsafe,
|
||||
// this will generate the Host header from the parsed baseURL
|
||||
if !unsafe && rawRequest.Headers["Host"] == "" {
|
||||
rawRequest.Headers["Host"] = hostURL
|
||||
}
|
||||
|
||||
|
|
|
@ -680,7 +680,7 @@ func init() {
|
|||
FieldName: "dns",
|
||||
},
|
||||
}
|
||||
DNSRequestDoc.Fields = make([]encoder.Doc, 9)
|
||||
DNSRequestDoc.Fields = make([]encoder.Doc, 10)
|
||||
DNSRequestDoc.Fields[0].Name = "matchers"
|
||||
DNSRequestDoc.Fields[0].Type = "[]matchers.Matcher"
|
||||
DNSRequestDoc.Fields[0].Note = ""
|
||||
|
@ -753,6 +753,11 @@ func init() {
|
|||
DNSRequestDoc.Fields[8].Note = ""
|
||||
DNSRequestDoc.Fields[8].Description = "Recursion determines if resolver should recurse all records to get fresh results."
|
||||
DNSRequestDoc.Fields[8].Comments[encoder.LineComment] = "Recursion determines if resolver should recurse all records to get fresh results."
|
||||
DNSRequestDoc.Fields[9].Name = "resolvers"
|
||||
DNSRequestDoc.Fields[9].Type = "[]string"
|
||||
DNSRequestDoc.Fields[9].Note = ""
|
||||
DNSRequestDoc.Fields[9].Description = "Resolvers to use for the dns requests"
|
||||
DNSRequestDoc.Fields[9].Comments[encoder.LineComment] = " Resolvers to use for the dns requests"
|
||||
|
||||
FILERequestDoc.Type = "file.Request"
|
||||
FILERequestDoc.Comments[encoder.LineComment] = " Request contains a File matching mechanism for local disk operations."
|
||||
|
|
|
@ -103,7 +103,9 @@ type Options struct {
|
|||
Headless bool
|
||||
// ShowBrowser specifies whether the show the browser in headless mode
|
||||
ShowBrowser bool
|
||||
// SytemResolvers enables override of nuclei's DNS client opting to use system resolver stack.
|
||||
// UseInstalledChrome skips chrome install and use local instance
|
||||
UseInstalledChrome bool
|
||||
// SystemResolvers enables override of nuclei's DNS client opting to use system resolver stack.
|
||||
SystemResolvers bool
|
||||
// Metrics enables display of metrics via an http endpoint
|
||||
Metrics bool
|
||||
|
|
Loading…
Reference in New Issue