Merge remote-tracking branch 'origin/dev' into colorize_responses

dev
forgedhallpass 2021-10-05 13:20:21 +03:00
commit 742a5c44fc
19 changed files with 160 additions and 104 deletions

View File

@ -1,8 +1,10 @@
name: 🌥 Docker Push
on:
release:
types: [published]
workflow_run:
workflows: ["🎉 Release Binary"]
types:
- completed
workflow_dispatch:
jobs:

View File

@ -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"]

View File

@ -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)

View File

@ -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 />

View File

@ -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,

View File

@ -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")
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
*/

View File

@ -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)
}

View File

@ -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

View File

@ -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 {

View File

@ -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")
}

View File

@ -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)

View File

@ -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 {

View File

@ -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
}

View File

@ -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."

View File

@ -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