Lint errors fix

This commit is contained in:
Ice3man543 2021-02-26 13:13:11 +05:30
parent b33bc83b0b
commit 8512b684c5
58 changed files with 364 additions and 432 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
cmd/nuclei/nuclei*
v2/cmd/nuclei/nuclei
.idea
integration_tests/integration-test
integration_tests/nuclei
v2/cmd/integration-test/integration-test

View File

@ -6,9 +6,9 @@ linters-settings:
# funlen:
# lines: 100
# statements: 50
goconst:
min-len: 2
min-occurrences: 2
#goconst:
# min-len: 2
# min-occurrences: 2
gocritic:
enabled-tags:
- diagnostic
@ -56,18 +56,18 @@ linters:
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
disable-all: true
enable:
- bodyclose
#- bodyclose
- deadcode
- dogsled
- errcheck
- exhaustive
- gochecknoinits
- goconst
#- goconst
- gocritic
- gofmt
- goimports
- golint
- gomnd
#- gomnd
- goprintffuncname
- gosimple
- govet

View File

@ -41,7 +41,7 @@ func httpDebugRequestDump(r *http.Request) {
type httpGetHeaders struct{}
// Executes executes a test case and returns an error if occured
// Executes 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) {
@ -65,7 +65,7 @@ func (h *httpGetHeaders) Execute(filePath string) error {
type httpGetQueryString struct{}
// Executes executes a test case and returns an error if occured
// Executes 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) {
@ -89,12 +89,12 @@ func (h *httpGetQueryString) Execute(filePath string) error {
type httpGetRedirects struct{}
// Executes executes a test case and returns an error if occured
// Executes 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) {
httpDebugRequestDump(r)
http.Redirect(w, r, "/redirected", 302)
http.Redirect(w, r, "/redirected", http.StatusFound)
}))
router.GET("/redirected", httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
httpDebugRequestDump(r)
@ -115,7 +115,7 @@ func (h *httpGetRedirects) Execute(filePath string) error {
type httpGet struct{}
// Executes executes a test case and returns an error if occured
// Executes 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) {
@ -137,7 +137,7 @@ func (h *httpGet) Execute(filePath string) error {
type httpPostBody struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpPostBody) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -170,7 +170,7 @@ func (h *httpPostBody) Execute(filePath string) error {
type httpPostJSONBody struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpPostJSONBody) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -209,7 +209,7 @@ func (h *httpPostJSONBody) Execute(filePath string) error {
type httpPostMultipartBody struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpPostMultipartBody) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -252,7 +252,7 @@ func (h *httpPostMultipartBody) Execute(filePath string) error {
type httpRawDynamicExtractor struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpRawDynamicExtractor) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -291,7 +291,7 @@ func (h *httpRawDynamicExtractor) Execute(filePath string) error {
type httpRawGetQuery struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpRawGetQuery) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -320,7 +320,7 @@ func (h *httpRawGetQuery) Execute(filePath string) error {
type httpRawGet struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpRawGet) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -348,7 +348,7 @@ func (h *httpRawGet) Execute(filePath string) error {
type httpRawPayload struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpRawPayload) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -384,7 +384,7 @@ func (h *httpRawPayload) Execute(filePath string) error {
type httpRawPostBody struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpRawPostBody) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -417,7 +417,7 @@ func (h *httpRawPostBody) Execute(filePath string) error {
type httpRawCookieReuse struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpRawCookieReuse) Execute(filePath string) error {
router := httprouter.New()
var routerErr error
@ -466,14 +466,14 @@ func (h *httpRawCookieReuse) Execute(filePath string) error {
type httpRawUnsafeRequest struct{}
// Executes executes a test case and returns an error if occured
// Executes executes a test case and returns an error if occurred
func (h *httpRawUnsafeRequest) Execute(filePath string) error {
var routerErr error
ts := testutils.NewTCPServer(func(conn net.Conn) {
defer conn.Close()
conn.Write([]byte("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 40\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Thu, 25 Feb 2021 17:17:28 GMT\r\n\r\nThis is test-raw-unsafe request matcher.\r\n"))
_, _ = conn.Write([]byte("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 40\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Thu, 25 Feb 2021 17:17:28 GMT\r\n\r\nThis is test-raw-unsafe request matcher.\r\n"))
})
defer ts.Close()

View File

@ -4,9 +4,6 @@ import (
"os"
"path"
"net/http"
_ "net/http/pprof"
"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v2/internal/runner"
@ -20,7 +17,6 @@ var (
func main() {
readConfig()
go http.ListenAndServe(":6060", http.DefaultServeMux)
runner.ParseOptions(options)

View File

@ -208,6 +208,7 @@ github.com/projectdiscovery/gologger v1.1.3 h1:rKWZW2QUigRV1jnlWwWJbJRvz8b+T/+bB
github.com/projectdiscovery/gologger v1.1.3/go.mod h1:jdXflz3TLB8bcVNzb0v26TztI9KPz8Lr4BVdUhNUs6E=
github.com/projectdiscovery/hmap v0.0.1 h1:VAONbJw5jP+syI5smhsfkrq9XPGn4aiYy5pR6KR1wog=
github.com/projectdiscovery/hmap v0.0.1/go.mod h1:VDEfgzkKQdq7iGTKz8Ooul0NuYHQ8qiDs6r8bPD1Sb0=
github.com/projectdiscovery/nuclei v1.1.7 h1:5Z1fBHcjyAuuI89xcCzv8tYK7b6ucqLxs+mCC/nJjno=
github.com/projectdiscovery/rawhttp v0.0.6 h1:HbgPB1eKXQVV5F9sq0Uxflm95spWFyZYD8dgFpeOC9M=
github.com/projectdiscovery/rawhttp v0.0.6/go.mod h1:PQERZAhAv7yxI/hR6hdDPgK1WTU56l204BweXrBec+0=
github.com/projectdiscovery/retryabledns v1.0.7 h1:fwbwrl+0XmWRvwiNzm/YSBjmUh7KwIsryScUK9juOuA=

View File

@ -8,8 +8,7 @@ type Colorizer struct {
}
const (
fgOrange uint8 = 208
undefined string = "undefined"
fgOrange uint8 = 208
)
// New returns a new severity based colorizer

View File

@ -1,10 +1,6 @@
package runner
import (
"fmt"
"os"
"path"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v2/pkg/templates"
"github.com/remeh/sizedwaitgroup"
@ -52,13 +48,3 @@ func (r *Runner) processWorkflowWithList(template *templates.Template) bool {
wg.Wait()
return results.Load()
}
// resolvePathWithBaseFolder resolves a path with the base folder
func resolvePathWithBaseFolder(baseFolder, templateName string) (string, error) {
templatePath := path.Join(baseFolder, templateName)
if _, err := os.Stat(templatePath); !os.IsNotExist(err) {
gologger.Debug().Msgf("Found template in current directory: %s\n", templatePath)
return templatePath, nil
}
return "", fmt.Errorf("no such path found: %s", templateName)
}

View File

@ -12,7 +12,7 @@ import (
"github.com/projectdiscovery/nuclei/v2/internal/collaborator"
"github.com/projectdiscovery/nuclei/v2/internal/colorizer"
"github.com/projectdiscovery/nuclei/v2/internal/progress"
"github.com/projectdiscovery/nuclei/v2/pkg/catalogue"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/projectfile"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
@ -35,7 +35,7 @@ type Runner struct {
templatesConfig *nucleiConfig
options *types.Options
projectFile *projectfile.ProjectFile
catalogue *catalogue.Catalogue
catalog *catalog.Catalog
progress *progress.Progress
colorizer aurora.Aurora
issuesClient *issues.Client
@ -63,7 +63,7 @@ func New(options *types.Options) (*Runner, error) {
if runner.templatesConfig != nil {
runner.readNucleiIgnoreFile()
}
runner.catalogue = catalogue.New(runner.options.TemplatesDirectory)
runner.catalog = catalog.New(runner.options.TemplatesDirectory)
if options.ReportingConfig != "" {
if client, err := issues.New(options.ReportingConfig, options.ReportingDB); err != nil {
@ -147,11 +147,11 @@ func New(options *types.Options) (*Runner, error) {
}
// Create the output file if asked
output, err := output.NewStandardWriter(!options.NoColor, options.NoMeta, options.JSON, options.Output, options.TraceLogFile)
outputWriter, err := output.NewStandardWriter(!options.NoColor, options.NoMeta, options.JSON, options.Output, options.TraceLogFile)
if err != nil {
gologger.Fatal().Msgf("Could not create output file '%s': %s\n", options.Output, err)
}
runner.output = output
runner.output = outputWriter
// Creates the progress tracking object
var progressErr error
@ -200,8 +200,8 @@ func (r *Runner) RunEnumeration() {
if len(r.options.Templates) == 0 && len(r.options.Tags) > 0 {
r.options.Templates = append(r.options.Templates, r.options.TemplatesDirectory)
}
includedTemplates := r.catalogue.GetTemplatesPath(r.options.Templates)
excludedTemplates := r.catalogue.GetTemplatesPath(r.options.ExcludedTemplates)
includedTemplates := r.catalog.GetTemplatesPath(r.options.Templates)
excludedTemplates := r.catalog.GetTemplatesPath(r.options.ExcludedTemplates)
// defaults to all templates
allTemplates := includedTemplates
@ -245,7 +245,7 @@ func (r *Runner) RunEnumeration() {
Output: r.output,
Options: r.options,
Progress: r.progress,
Catalogue: r.catalogue,
Catalog: r.catalog,
RateLimiter: r.ratelimiter,
IssuesClient: r.issuesClient,
Browser: r.browser,
@ -261,9 +261,7 @@ func (r *Runner) RunEnumeration() {
})
clusterCount += len(cluster)
} else {
for _, item := range cluster {
finalTemplates = append(finalTemplates, item)
}
finalTemplates = append(finalTemplates, cluster...)
}
}

View File

@ -14,13 +14,12 @@ import (
// getParsedTemplatesFor parse the specified templates and returns a slice of the parsable ones, optionally filtered
// by severity, along with a flag indicating if workflows are present.
func (r *Runner) getParsedTemplatesFor(templatePaths []string, severities []string) (map[string]*templates.Template, int) {
workflowCount := 0
func (r *Runner) getParsedTemplatesFor(templatePaths, severities []string) (parsedTemplates map[string]*templates.Template, workflowCount int) {
filterBySeverity := len(severities) > 0
gologger.Info().Msgf("Loading templates...")
parsedTemplates := make(map[string]*templates.Template)
parsedTemplates = make(map[string]*templates.Template)
for _, match := range templatePaths {
t, err := r.parseTemplateFile(match)
if err != nil {
@ -50,7 +49,7 @@ func (r *Runner) parseTemplateFile(file string) (*templates.Template, error) {
Output: r.output,
Options: r.options,
Progress: r.progress,
Catalogue: r.catalogue,
Catalog: r.catalog,
IssuesClient: r.issuesClient,
RateLimiter: r.ratelimiter,
ProjectFile: r.projectFile,
@ -143,20 +142,3 @@ func directoryWalker(fsPath string, callback func(fsPath string, d *godirwalk.Di
return nil
}
func isFilePath(filePath string) (bool, error) {
info, err := os.Stat(filePath)
if err != nil {
return false, err
}
return info.Mode().IsRegular(), nil
}
func isNewPath(filePath string, pathMap map[string]bool) bool {
if _, already := pathMap[filePath]; already {
gologger.Warning().Msgf("Skipping already specified path '%s'", filePath)
return false
}
return true
}

View File

@ -278,15 +278,14 @@ func (r *Runner) downloadReleaseAndUnzip(ctx context.Context, version, downloadU
// If we don't find a previous file in new download and it hasn't been
// changed on the disk, delete it.
if previousChecksum != nil {
for k, v := range previousChecksum {
_, ok := checksums[k]
if !ok && v[0] == v[1] {
os.Remove(k)
deletions = append(deletions, strings.TrimPrefix(strings.TrimPrefix(k, r.templatesConfig.TemplatesDirectory), "/"))
}
for k, v := range previousChecksum {
_, ok := checksums[k]
if !ok && v[0] == v[1] {
os.Remove(k)
deletions = append(deletions, strings.TrimPrefix(strings.TrimPrefix(k, r.templatesConfig.TemplatesDirectory), "/"))
}
}
r.printUpdateChangelog(additions, modifications, deletions, version, totalCount)
return writeTemplatesChecksum(checksumFile, checksums)
}
@ -342,10 +341,10 @@ func writeTemplatesChecksum(file string, checksum map[string]string) error {
defer f.Close()
for k, v := range checksum {
f.WriteString(k)
f.WriteString(",")
f.WriteString(v)
f.WriteString("\n")
_, _ = f.WriteString(k)
_, _ = f.WriteString(",")
_, _ = f.WriteString(v)
_, _ = f.WriteString("\n")
}
return nil
}

View File

@ -8,10 +8,10 @@ import (
)
// RunNucleiAndGetResults returns a list of results for a template
func RunNucleiAndGetResults(template string, URL string, debug bool) ([]string, error) {
cmd := exec.Command("./nuclei", "-t", template, "-target", URL)
func RunNucleiAndGetResults(template, url string, debug bool) ([]string, error) {
cmd := exec.Command("./nuclei", "-t", template, "-target", url)
if debug {
cmd = exec.Command("./nuclei", "-t", template, "-target", URL, "-debug")
cmd = exec.Command("./nuclei", "-t", template, "-target", url, "-debug")
cmd.Stderr = os.Stderr
}
data, err := cmd.Output()
@ -30,7 +30,7 @@ func RunNucleiAndGetResults(template string, URL string, debug bool) ([]string,
// TestCase is a single integration test case
type TestCase interface {
// Execute executes a test case and returns any errors if occured
// Execute executes a test case and returns any errors if occurred
Execute(filePath string) error
}

View File

@ -3,7 +3,7 @@ package testutils
import (
"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/nuclei/v2/internal/progress"
"github.com/projectdiscovery/nuclei/v2/pkg/catalogue"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolinit"
@ -13,7 +13,7 @@ import (
// Init initializes the protocols and their configurations
func Init(options *types.Options) {
protocolinit.Init(options)
_ = protocolinit.Init(options)
}
// DefaultOptions is the default options structure for nuclei during mocking.
@ -102,18 +102,18 @@ type TemplateInfo struct {
// NewMockExecuterOptions creates a new mock executeroptions struct
func NewMockExecuterOptions(options *types.Options, info *TemplateInfo) *protocols.ExecuterOptions {
progress, _ := progress.NewProgress(0, false, false, 0)
progressImpl, _ := progress.NewProgress(0, false, false, 0)
executerOpts := &protocols.ExecuterOptions{
TemplateID: info.ID,
TemplateInfo: info.Info,
TemplatePath: info.Path,
Output: NewMockOutputWriter(),
Options: options,
Progress: progress,
Progress: progressImpl,
ProjectFile: nil,
IssuesClient: nil,
Browser: nil,
Catalogue: catalogue.New(options.TemplatesDirectory),
Catalog: catalog.New(options.TemplatesDirectory),
RateLimiter: ratelimit.New(options.RateLimit),
}
return executerOpts

View File

@ -0,0 +1,14 @@
package catalog
// Catalog is a template catalog helper implementation
type Catalog struct {
ignoreFiles []string
templatesDirectory string
}
// New creates a new Catalog structure using provided input items
func New(directory string) *Catalog {
catalog := &Catalog{templatesDirectory: directory}
catalog.readNucleiIgnoreFile()
return catalog
}

View File

@ -1,4 +1,4 @@
package catalogue
package catalog
import (
"os"
@ -12,7 +12,7 @@ import (
)
// GetTemplatesPath returns a list of absolute paths for the provided template list.
func (c *Catalogue) GetTemplatesPath(definitions []string) []string {
func (c *Catalog) GetTemplatesPath(definitions []string) []string {
// keeps track of processed dirs and files
processed := make(map[string]bool)
allTemplates := []string{}
@ -38,7 +38,7 @@ func (c *Catalogue) GetTemplatesPath(definitions []string) []string {
// GetTemplatePath parses the specified input template path and returns a compiled
// list of finished absolute paths to the templates evaluating any glob patterns
// or folders provided as in.
func (c *Catalogue) GetTemplatePath(target string) ([]string, error) {
func (c *Catalog) GetTemplatePath(target string) ([]string, error) {
processed := make(map[string]struct{})
absPath, err := c.convertPathToAbsolute(target)
@ -48,9 +48,9 @@ func (c *Catalogue) GetTemplatePath(target string) ([]string, error) {
// Template input includes a wildcard
if strings.Contains(absPath, "*") {
matches, err := c.findGlobPathMatches(absPath, processed)
if err != nil {
return nil, errors.Wrap(err, "could not find glob matches")
matches, findErr := c.findGlobPathMatches(absPath, processed)
if findErr != nil {
return nil, errors.Wrap(findErr, "could not find glob matches")
}
if len(matches) == 0 {
return nil, errors.Errorf("no templates found for path")
@ -84,7 +84,7 @@ func (c *Catalogue) GetTemplatePath(target string) ([]string, error) {
// convertPathToAbsolute resolves the paths provided to absolute paths
// before doing any operations on them regardless of them being blob, folders, files, etc.
func (c *Catalogue) convertPathToAbsolute(t string) (string, error) {
func (c *Catalog) convertPathToAbsolute(t string) (string, error) {
if strings.Contains(t, "*") {
file := path.Base(t)
absPath, err := c.ResolvePath(path.Dir(t), "")
@ -97,7 +97,7 @@ func (c *Catalogue) convertPathToAbsolute(t string) (string, error) {
}
// findGlobPathMatches returns the matched files from a glob path
func (c *Catalogue) findGlobPathMatches(absPath string, processed map[string]struct{}) ([]string, error) {
func (c *Catalog) findGlobPathMatches(absPath string, processed map[string]struct{}) ([]string, error) {
matches, err := filepath.Glob(absPath)
if err != nil {
return nil, errors.Errorf("wildcard found, but unable to glob: %s\n", err)
@ -114,7 +114,7 @@ func (c *Catalogue) findGlobPathMatches(absPath string, processed map[string]str
// findFileMatches finds if a path is an absolute file. If the path
// is a file, it returns true otherwise false with no errors.
func (c *Catalogue) findFileMatches(absPath string, processed map[string]struct{}) (string, bool, error) {
func (c *Catalog) findFileMatches(absPath string, processed map[string]struct{}) (match string, matched bool, err error) {
info, err := os.Stat(absPath)
if err != nil {
return "", false, err
@ -130,7 +130,7 @@ func (c *Catalogue) findFileMatches(absPath string, processed map[string]struct{
}
// findDirectoryMatches finds matches for templates from a directory
func (c *Catalogue) findDirectoryMatches(absPath string, processed map[string]struct{}) ([]string, error) {
func (c *Catalog) findDirectoryMatches(absPath string, processed map[string]struct{}) ([]string, error) {
var results []string
err := godirwalk.Walk(absPath, &godirwalk.Options{
Unsorted: true,

View File

@ -1,4 +1,4 @@
package catalogue
package catalog
import (
"bufio"
@ -12,7 +12,7 @@ import (
const nucleiIgnoreFile = ".nuclei-ignore"
// readNucleiIgnoreFile reads the nuclei ignore file marking it in map
func (c *Catalogue) readNucleiIgnoreFile() {
func (c *Catalog) readNucleiIgnoreFile() {
file, err := os.Open(path.Join(c.templatesDirectory, nucleiIgnoreFile))
if err != nil {
return
@ -33,7 +33,7 @@ func (c *Catalogue) readNucleiIgnoreFile() {
}
// checkIfInNucleiIgnore checks if a path falls under nuclei-ignore rules.
func (c *Catalogue) checkIfInNucleiIgnore(item string) bool {
func (c *Catalog) checkIfInNucleiIgnore(item string) bool {
if c.templatesDirectory == "" {
return false
}
@ -54,7 +54,7 @@ func (c *Catalogue) checkIfInNucleiIgnore(item string) bool {
}
// ignoreFilesWithExcludes ignores results with exclude paths
func (c *Catalogue) ignoreFilesWithExcludes(results, excluded []string) []string {
func (c *Catalog) ignoreFilesWithExcludes(results, excluded []string) []string {
var templates []string
for _, result := range results {

View File

@ -1,4 +1,4 @@
package catalogue
package catalog
import (
"testing"
@ -7,7 +7,7 @@ import (
)
func TestIgnoreFilesIgnore(t *testing.T) {
c := &Catalogue{
c := &Catalog{
ignoreFiles: []string{"workflows/", "cves/2020/cve-2020-5432.yaml"},
templatesDirectory: "test",
}
@ -30,7 +30,7 @@ func TestIgnoreFilesIgnore(t *testing.T) {
}
func TestExcludeFilesIgnore(t *testing.T) {
c := &Catalogue{}
c := &Catalog{}
excludes := []string{"workflows/", "cves/2020/cve-2020-5432.yaml"}
paths := []string{"/Users/test/nuclei-templates/workflows/", "/Users/test/nuclei-templates/cves/2020/cve-2020-5432.yaml", "/Users/test/nuclei-templates/workflows/test-workflow.yaml", "/Users/test/nuclei-templates/cves/"}

View File

@ -1,4 +1,4 @@
package catalogue
package catalog
import (
"fmt"
@ -13,7 +13,7 @@ import (
// It checks if the filename is an absolute path, looks in the current directory
// or checking the nuclei templates directory. If a second path is given,
// it also tries to find paths relative to that second path.
func (c *Catalogue) ResolvePath(templateName, second string) (string, error) {
func (c *Catalog) ResolvePath(templateName, second string) (string, error) {
if strings.HasPrefix(templateName, "/") || strings.Contains(templateName, ":\\") {
return templateName, nil
}

View File

@ -1,14 +0,0 @@
package catalogue
// Catalogue is a template catalouge helper implementation
type Catalogue struct {
ignoreFiles []string
templatesDirectory string
}
// New creates a new catalogue structure using provided input items
func New(directory string) *Catalogue {
catalogue := &Catalogue{templatesDirectory: directory}
catalogue.readNucleiIgnoreFile()
return catalogue
}

View File

@ -14,8 +14,7 @@ func (m *Matcher) CompileMatchers() error {
var ok bool
// Support hexadecimal encoding for matchers too.
switch m.Encoding {
case "hex":
if m.Encoding == "hex" {
for i, word := range m.Words {
if decoded, err := hex.DecodeString(word); err == nil && len(decoded) > 0 {
m.Words[i] = string(decoded)

View File

@ -7,7 +7,7 @@ import (
)
// formatScreen formats the output for showing on screen.
func (w *StandardWriter) formatScreen(output *ResultEvent) ([]byte, error) {
func (w *StandardWriter) formatScreen(output *ResultEvent) []byte {
builder := &bytes.Buffer{}
if !w.noMetadata {
@ -63,5 +63,5 @@ func (w *StandardWriter) formatScreen(output *ResultEvent) ([]byte, error) {
}
builder.WriteString("]")
}
return builder.Bytes(), nil
return builder.Bytes()
}

View File

@ -120,7 +120,7 @@ func (w *StandardWriter) Write(event *ResultEvent) error {
if w.json {
data, err = w.formatJSON(event)
} else {
data, err = w.formatScreen(event)
data = w.formatScreen(event)
}
if err != nil {
return errors.Wrap(err, "could not format output")

View File

@ -6,7 +6,7 @@ import (
"testing"
"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/nuclei/v2/pkg/catalogue"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolinit"
@ -16,18 +16,18 @@ import (
)
func TestHTTPRequestsCluster(t *testing.T) {
catalogue := catalogue.New("/Users/ice3man/nuclei-templates")
templatesList, err := catalogue.GetTemplatePath("/Users/ice3man/nuclei-templates")
catalogImpl := catalog.New("/Users/ice3man/nuclei-templates")
templatesList, err := catalogImpl.GetTemplatePath("/Users/ice3man/nuclei-templates")
require.Nil(t, err, "could not get templates")
protocolinit.Init(&types.Options{})
_ = protocolinit.Init(&types.Options{})
list := make(map[string]*templates.Template)
for _, template := range templatesList {
executerOpts := protocols.ExecuterOptions{
Output: &mockOutput{},
Options: &types.Options{},
Progress: nil,
Catalogue: catalogue,
Catalog: catalogImpl,
RateLimiter: nil,
IssuesClient: nil,
ProjectFile: nil,
@ -45,8 +45,8 @@ func TestHTTPRequestsCluster(t *testing.T) {
totalClusterCount := 0
totalRequestsSentNew := 0
new := Cluster(list)
for i, cluster := range new {
newRequests := Cluster(list)
for i, cluster := range newRequests {
if len(cluster) == 1 {
continue
}

View File

@ -76,7 +76,7 @@ func (e *Executer) Execute(input string) (bool, error) {
gologger.Warning().Msgf("Could not create issue on tracker: %s", err)
}
}
e.options.Output.Write(r)
_ = e.options.Output.Write(r)
e.options.Progress.IncrementMatched()
}
}

View File

@ -48,6 +48,8 @@ func (e *Executer) Execute(input string) (bool, error) {
dynamicValues := make(map[string]interface{})
previous := make(map[string]interface{})
for _, req := range e.requests {
req := req
err := req.ExecuteWithResults(input, dynamicValues, previous, func(event *output.InternalWrappedEvent) {
ID := req.GetID()
if ID != "" {
@ -70,7 +72,7 @@ func (e *Executer) Execute(input string) (bool, error) {
}
}
results = true
e.options.Output.Write(result)
_ = e.options.Output.Write(result)
e.options.Progress.IncrementMatched()
}
})
@ -87,6 +89,8 @@ func (e *Executer) ExecuteWithResults(input string, callback protocols.OutputEve
previous := make(map[string]interface{})
for _, req := range e.requests {
req := req
err := req.ExecuteWithResults(input, dynamicValues, previous, func(event *output.InternalWrappedEvent) {
ID := req.GetID()
if ID != "" {

View File

@ -32,7 +32,7 @@ var StringToType = map[string]Type{
}
// New creates a new generator structure for payload generation
func New(payloads map[string]interface{}, Type Type, templatePath string) (*Generator, error) {
func New(payloads map[string]interface{}, payloadType Type, templatePath string) (*Generator, error) {
generator := &Generator{}
if err := generator.validate(payloads, templatePath); err != nil {
return nil, err
@ -42,11 +42,11 @@ func New(payloads map[string]interface{}, Type Type, templatePath string) (*Gene
if err != nil {
return nil, err
}
generator.Type = Type
generator.Type = payloadType
generator.payloads = compiled
// Validate the payload types
if Type == PitchFork {
if payloadType == PitchFork {
var totalLength int
for v := range compiled {
if totalLength != 0 && totalLength != len(v) {
@ -110,7 +110,7 @@ func (i *Iterator) Total() int {
case ClusterBomb:
count = 1
for _, p := range i.payloads {
count = count * len(p.values)
count *= len(p.values)
}
}
return count

View File

@ -13,7 +13,7 @@ const (
// Replace replaces placeholders in template with values on the fly.
func Replace(template string, values map[string]interface{}) string {
new := fasttemplate.ExecuteStringStd(template, MarkerGeneral, MarkerGeneral, values)
final := fasttemplate.ExecuteStringStd(new, MarkerParenthesisOpen, MarkerParenthesisClose, values)
newResult := fasttemplate.ExecuteStringStd(template, MarkerGeneral, MarkerGeneral, values)
final := fasttemplate.ExecuteStringStd(newResult, MarkerParenthesisOpen, MarkerParenthesisClose, values)
return final
}

View File

@ -15,10 +15,11 @@ import (
// Request contains a DNS protocol request to be made from a template
type Request struct {
// Operators for the current request go here.
operators.Operators `yaml:",inline"`
ID string `yaml:"id"`
// Recursion specifies whether to recurse all the answers.
Recursion bool `yaml:"recursion"`
// Path contains the path/s for the request
Name string `yaml:"name"`
// Type is the type of DNS request to make
@ -28,15 +29,16 @@ type Request struct {
// Retries is the number of retries for the DNS request
Retries int `yaml:"retries"`
// Operators for the current request go here.
operators.Operators `yaml:",inline"`
CompiledOperators *operators.Operators
CompiledOperators *operators.Operators
dnsClient *retryabledns.Client
options *protocols.ExecuterOptions
// cache any variables that may be needed for operation.
class uint16
question uint16
dnsClient *retryabledns.Client
options *protocols.ExecuterOptions
class uint16
question uint16
// Recursion specifies whether to recurse all the answers.
Recursion bool `yaml:"recursion"`
}
// GetID returns the unique ID of the request if any.
@ -97,11 +99,11 @@ func (r *Request) Make(domain string) (*dns.Msg, error) {
}
// questionTypeToInt converts DNS question type to internal representation
func questionTypeToInt(Type string) uint16 {
Type = strings.TrimSpace(strings.ToUpper(Type))
func questionTypeToInt(questionType string) uint16 {
questionType = strings.TrimSpace(strings.ToUpper(questionType))
question := dns.TypeA
switch Type {
switch questionType {
case "A":
question = dns.TypeA
case "NS":
@ -119,7 +121,7 @@ func questionTypeToInt(Type string) uint16 {
case "AAAA":
question = dns.TypeAAAA
}
return uint16(question)
return question
}
// classToInt converts a dns class name to it's internal representation

View File

@ -11,7 +11,7 @@ func TestDNSCompileMake(t *testing.T) {
options := testutils.DefaultOptions
testutils.Init(options)
templateID := "testing-dns"
const templateID = "testing-dns"
request := &Request{
Type: "A",
Class: "INET",

View File

@ -8,28 +8,30 @@ import (
// Request contains a File matching mechanism for local disk operations.
type Request struct {
ID string `yaml:"id"`
// MaxSize is the maximum size of the file to run request on.
// By default, nuclei will process 5MB files and not go more than that.
// It can be set to much lower or higher depending on use.
MaxSize int `yaml:"max-size"`
// NoRecursive specifies whether to not do recursive checks if folders are provided.
NoRecursive bool `yaml:"no-recursive"`
// Operators for the current request go here.
operators.Operators `yaml:",inline"`
// Extensions is the list of extensions to perform matching on.
Extensions []string `yaml:"extensions"`
// ExtensionDenylist is the list of file extensions to deny during matching.
ExtensionDenylist []string `yaml:"denylist"`
// Operators for the current request go here.
operators.Operators `yaml:",inline"`
CompiledOperators *operators.Operators
ID string `yaml:"id"`
// MaxSize is the maximum size of the file to run request on.
// By default, nuclei will process 5MB files and not go more than that.
// It can be set to much lower or higher depending on use.
MaxSize int `yaml:"max-size"`
CompiledOperators *operators.Operators
// cache any variables that may be needed for operation.
options *protocols.ExecuterOptions
extensions map[string]struct{}
allExtensions bool
extensionDenylist map[string]struct{}
// NoRecursive specifies whether to not do recursive checks if folders are provided.
NoRecursive bool `yaml:"no-recursive"`
allExtensions bool
}
// defaultDenylist is the default list of extensions to be denied

View File

@ -62,7 +62,7 @@ func (r *Request) Extract(data map[string]interface{}, extractor *extractors.Ext
}
// responseToDSLMap converts a DNS response to a map for use in DSL matching
func (r *Request) responseToDSLMap(raw string, host, matched string) output.InternalEvent {
func (r *Request) responseToDSLMap(raw, host, matched string) output.InternalEvent {
data := make(output.InternalEvent, 5)
// Some data regarding the request metadata

View File

@ -31,7 +31,7 @@ func New(options *types.Options) (*Browser, error) {
if err != nil {
return nil, errors.Wrap(err, "could not create temporary directory")
}
launcher := launcher.New().
chromeLauncher := launcher.New().
Leakless(false).
Set("disable-gpu", "true").
Set("ignore-certificate-errors", "true").
@ -47,21 +47,21 @@ func New(options *types.Options) (*Browser, error) {
UserDataDir(dataStore)
if options.ShowBrowser {
launcher = launcher.Headless(false)
chromeLauncher = chromeLauncher.Headless(false)
} else {
launcher = launcher.Headless(true)
chromeLauncher = chromeLauncher.Headless(true)
}
if options.ProxyURL != "" {
launcher = launcher.Proxy(options.ProxyURL)
chromeLauncher = chromeLauncher.Proxy(options.ProxyURL)
}
launcherURL, err := launcher.Launch()
launcherURL, err := chromeLauncher.Launch()
if err != nil {
return nil, err
}
browser := rod.New().ControlURL(launcherURL)
if err := browser.Connect(); err != nil {
return nil, err
if browserErr := browser.Connect(); browserErr != nil {
return nil, browserErr
}
customAgent := ""
for _, option := range options.CustomHeaders {
@ -101,8 +101,8 @@ func (b *Browser) Close() {
// killChromeProcesses any and all new chrome processes started after
// headless process launch.
func (b *Browser) killChromeProcesses() {
new := b.findChromeProcesses()
for id := range new {
newProcesses := b.findChromeProcesses()
for id := range newProcesses {
if _, ok := b.previouspids[id]; ok {
continue
}

View File

@ -22,15 +22,15 @@ func (i *Instance) Run(baseURL *url.URL, actions []*Action) (map[string]string,
return nil, nil, err
}
if i.browser.customAgent != "" {
if err := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: i.browser.customAgent}); err != nil {
return nil, nil, err
if userAgentErr := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: i.browser.customAgent}); userAgentErr != nil {
return nil, nil, userAgentErr
}
}
createdPage := &Page{page: page, instance: i}
router := page.HijackRequests()
if err := router.Add("*", "", createdPage.routingRuleHandler); err != nil {
return nil, nil, err
if routerErr := router.Add("*", "", createdPage.routingRuleHandler); routerErr != nil {
return nil, nil, routerErr
}
createdPage.router = router
@ -57,7 +57,7 @@ func (i *Instance) Run(baseURL *url.URL, actions []*Action) (map[string]string,
// Close closes a browser page
func (p *Page) Close() {
p.router.Stop()
_ = p.router.Stop()
p.page.Close()
}

View File

@ -67,7 +67,7 @@ func (p *Page) ExecuteActions(baseURL *url.URL, actions []*Action) (map[string]s
continue
}
if err != nil {
return nil, errors.Wrap(err, "error occured executing action")
return nil, errors.Wrap(err, "error occurred executing action")
}
}
return outData, nil
@ -158,20 +158,20 @@ func (p *Page) ActionSetMethod(act *Action, out map[string]string) error {
// NavigateURL executes an ActionLoadURL actions loading a URL for the page.
func (p *Page) NavigateURL(action *Action, out map[string]string, parsed *url.URL) error {
url := action.GetArg("url")
if url == "" {
URL := action.GetArg("url")
if URL == "" {
return errors.New("invalid arguments provided")
}
// Handle the dynamic value substituion here.
url, parsed = baseURLWithTemplatePrefs(url, parsed)
// Handle the dynamic value substitution here.
URL, parsed = baseURLWithTemplatePrefs(URL, parsed)
values := map[string]interface{}{"Hostname": parsed.Hostname()}
if strings.HasSuffix(parsed.Path, "/") && strings.Contains(url, "{{BaseURL}}/") {
if strings.HasSuffix(parsed.Path, "/") && strings.Contains(URL, "{{BaseURL}}/") {
parsed.Path = strings.TrimSuffix(parsed.Path, "/")
}
parsedString := parsed.String()
values["BaseURL"] = parsedString
final := fasttemplate.ExecuteStringStd(url, "{{", "}}", values)
final := fasttemplate.ExecuteStringStd(URL, "{{", "}}", values)
err := p.page.Navigate(final)
if err != nil {
return errors.Wrap(err, "could not navigate")
@ -476,8 +476,6 @@ func selectorBy(selector string) rod.SelectorType {
return rod.SelectorTypeCSSSector
case "regex":
return rod.SelectorTypeRegex
case "text":
fallthrough
default:
return rod.SelectorTypeText
}

View File

@ -27,7 +27,7 @@ func (p *Page) routingRuleHandler(ctx *rod.Hijack) {
ctx.Request.SetBody(body)
}
}
ctx.LoadResponse(p.instance.browser.httpclient, true)
_ = ctx.LoadResponse(p.instance.browser.httpclient, true)
for _, rule := range p.rules {
if rule.Part != "response" {

View File

@ -62,7 +62,7 @@ func (r *Request) Extract(data map[string]interface{}, extractor *extractors.Ext
}
// responseToDSLMap converts a DNS response to a map for use in DSL matching
func (r *Request) responseToDSLMap(resp, req string, host, matched string) output.InternalEvent {
func (r *Request) responseToDSLMap(resp, req, host, matched string) output.InternalEvent {
data := make(output.InternalEvent, 5)
// Some data regarding the request metadata

View File

@ -51,7 +51,7 @@ func (r *requestGenerator) Make(baseURL string, dynamicValues map[string]interfa
data, parsed = baseURLWithTemplatePrefs(data, parsed)
values := generators.MergeMaps(dynamicValues, map[string]interface{}{
"Hostname": parsed.Hostname(),
"Hostname": parsed.Host,
})
isRawRequest := len(r.request.Raw) > 0

View File

@ -116,8 +116,8 @@ func (r *Request) Compile(options *protocols.ExecuterOptions) error {
}
if len(r.Matchers) > 0 || len(r.Extractors) > 0 {
compiled := &r.Operators
if err := compiled.Compile(); err != nil {
return errors.Wrap(err, "could not compile operators")
if compileErr := compiled.Compile(); compileErr != nil {
return errors.Wrap(compileErr, "could not compile operators")
}
r.CompiledOperators = compiled
}
@ -131,16 +131,15 @@ func (r *Request) Compile(options *protocols.ExecuterOptions) error {
// Resolve payload paths if they are files.
for name, payload := range r.Payloads {
switch pt := payload.(type) {
case string:
final, err := options.Catalogue.ResolvePath(pt, options.TemplatePath)
if err != nil {
return errors.Wrap(err, "could not read payload file")
payloadStr, ok := payload.(string)
if ok {
final, resolveErr := options.Catalog.ResolvePath(payloadStr, options.TemplatePath)
if resolveErr != nil {
return errors.Wrap(resolveErr, "could not read payload file")
}
r.Payloads[name] = final
}
}
r.generator, err = generators.New(r.Payloads, r.attackType, r.options.TemplatePath)
if err != nil {
return errors.Wrap(err, "could not parse payloads")
@ -160,7 +159,7 @@ func (r *Request) Requests() int {
if len(r.Raw) > 0 {
requests := len(r.Raw)
if requests == 1 && r.RaceNumberRequests != 0 {
requests = requests * r.RaceNumberRequests
requests *= r.RaceNumberRequests
}
return requests
}

View File

@ -49,12 +49,12 @@ func Init(options *types.Options) error {
// Configuration contains the custom configuration options for a client
type Configuration struct {
// CookieReuse enables cookie reuse for the http client (cookiejar impl)
CookieReuse bool
// Threads contains the threads for the client
Threads int
// MaxRedirects is the maximum number of redirects to follow
MaxRedirects int
// CookieReuse enables cookie reuse for the http client (cookiejar impl)
CookieReuse bool
// FollowRedirects specifies whether to follow redirects
FollowRedirects bool
}
@ -161,17 +161,17 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
if options.ProxySocksURL != "" {
var proxyAuth *proxy.Auth
socksURL, err := url.Parse(options.ProxySocksURL)
if err == nil {
socksURL, proxyErr := url.Parse(options.ProxySocksURL)
if proxyErr == nil {
proxyAuth = &proxy.Auth{}
proxyAuth.User = socksURL.User.Username()
proxyAuth.Password, _ = socksURL.User.Password()
}
dialer, err := proxy.SOCKS5("tcp", fmt.Sprintf("%s:%s", socksURL.Hostname(), socksURL.Port()), proxyAuth, proxy.Direct)
dialer, proxyErr := proxy.SOCKS5("tcp", fmt.Sprintf("%s:%s", socksURL.Hostname(), socksURL.Port()), proxyAuth, proxy.Direct)
dc := dialer.(interface {
DialContext(ctx context.Context, network, addr string) (net.Conn, error)
})
if err == nil {
if proxyErr == nil {
transport.DialContext = dc.DialContext
}
}

View File

@ -94,7 +94,7 @@ func (r *Request) responseToDSLMap(resp *http.Response, host, matched, rawReq, r
data[strings.ToLower(cookie.Name)] = cookie.Value
}
for k, v := range resp.Header {
k = strings.ToLower(strings.Replace(strings.TrimSpace(k), "-", "_", -1))
k = strings.ToLower(strings.ReplaceAll(strings.TrimSpace(k), "-", "_"))
data[k] = strings.Join(v, " ")
}
data["all_headers"] = headers

View File

@ -41,7 +41,6 @@ func Parse(request, baseURL string, unsafe bool) (*Request, error) {
}
parts := strings.Split(s, " ")
//nolint:gomnd // this is not a magic number
if len(parts) < 3 && !unsafe {
return nil, fmt.Errorf("malformed request supplied")
}

View File

@ -26,7 +26,7 @@ import (
const defaultMaxWorkers = 150
// executeRaceRequest executes race condition request for a URL
func (r *Request) executeRaceRequest(reqURL string, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
func (r *Request) executeRaceRequest(reqURL string, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
generator := r.newGenerator()
maxWorkers := r.RaceNumberRequests
@ -42,7 +42,7 @@ func (r *Request) executeRaceRequest(reqURL string, dynamicValues, previous outp
for i := 0; i < r.RaceNumberRequests; i++ {
swg.Add()
go func(httpRequest *generatedRequest) {
err := r.executeRequest(reqURL, httpRequest, dynamicValues, previous, callback)
err := r.executeRequest(reqURL, httpRequest, previous, callback)
mutex.Lock()
if err != nil {
requestErr = multierr.Append(requestErr, err)
@ -79,7 +79,7 @@ func (r *Request) executeParallelHTTP(reqURL string, dynamicValues, previous out
defer swg.Done()
r.options.RateLimiter.Take()
err := r.executeRequest(reqURL, httpRequest, dynamicValues, previous, callback)
err := r.executeRequest(reqURL, httpRequest, previous, callback)
mutex.Lock()
if err != nil {
requestErr = multierr.Append(requestErr, err)
@ -138,7 +138,7 @@ func (r *Request) executeTurboHTTP(reqURL string, dynamicValues, previous output
go func(httpRequest *generatedRequest) {
defer swg.Done()
err := r.executeRequest(reqURL, httpRequest, dynamicValues, previous, callback)
err := r.executeRequest(reqURL, httpRequest, previous, callback)
mutex.Lock()
if err != nil {
requestErr = multierr.Append(requestErr, err)
@ -160,7 +160,7 @@ func (r *Request) ExecuteWithResults(reqURL string, dynamicValues, previous outp
// verify if a basic race condition was requested
if r.Race && r.RaceNumberRequests > 0 {
return r.executeRaceRequest(reqURL, dynamicValues, previous, callback)
return r.executeRaceRequest(reqURL, previous, callback)
}
// verify if parallel elaboration was requested
@ -183,7 +183,7 @@ func (r *Request) ExecuteWithResults(reqURL string, dynamicValues, previous outp
var gotOutput bool
r.options.RateLimiter.Take()
err = r.executeRequest(reqURL, request, dynamicValues, previous, func(event *output.InternalWrappedEvent) {
err = r.executeRequest(reqURL, request, previous, func(event *output.InternalWrappedEvent) {
// Add the extracts to the dynamic values if any.
if event.OperatorsResult != nil {
gotOutput = true
@ -206,8 +206,8 @@ func (r *Request) ExecuteWithResults(reqURL string, dynamicValues, previous outp
const drainReqSize = int64(8 * 1024)
// executeRequest executes the actual generated request and returns error if occured
func (r *Request) executeRequest(reqURL string, request *generatedRequest, dynamicvalues, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
// executeRequest executes the actual generated request and returns error if occurred
func (r *Request) executeRequest(reqURL string, request *generatedRequest, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
r.setCustomHeaders(request)
var (
@ -235,27 +235,26 @@ func (r *Request) executeRequest(reqURL string, request *generatedRequest, dynam
timeStart := time.Now()
if request.original.Pipeline {
formedURL = request.rawRequest.FullURL
if parsed, err := url.Parse(formedURL); err == nil {
hostname = parsed.Hostname()
if parsed, parseErr := url.Parse(formedURL); parseErr == nil {
hostname = parsed.Host
}
resp, err = request.pipelinedClient.DoRaw(request.rawRequest.Method, reqURL, request.rawRequest.Path, generators.ExpandMapValues(request.rawRequest.Headers), ioutil.NopCloser(strings.NewReader(request.rawRequest.Data)))
} else if request.original.Unsafe && request.rawRequest != nil {
formedURL = request.rawRequest.FullURL
if parsed, err := url.Parse(formedURL); err == nil {
hostname = parsed.Hostname()
if parsed, parseErr := url.Parse(formedURL); parseErr == nil {
hostname = parsed.Host
}
options := request.original.rawhttpClient.Options
options.FollowRedirects = r.Redirects
options.CustomRawBytes = []byte(request.rawRequest.UnsafeRawBytes)
options.CustomRawBytes = request.rawRequest.UnsafeRawBytes
resp, err = request.original.rawhttpClient.DoRawWithOptions(request.rawRequest.Method, reqURL, request.rawRequest.Path, generators.ExpandMapValues(request.rawRequest.Headers), ioutil.NopCloser(strings.NewReader(request.rawRequest.Data)), options)
} else {
hostname = request.request.URL.Hostname()
hostname = request.request.URL.Host
formedURL = request.request.URL.String()
// if nuclei-project is available check if the request was already sent previously
if r.options.ProjectFile != nil {
// if unavailable fail silently
fromcache = true
// nolint:bodyclose // false positive the response is generated at runtime
resp, err = r.options.ProjectFile.Get(dumpedRequest)
if err != nil {
fromcache = false
@ -278,6 +277,10 @@ func (r *Request) executeRequest(reqURL string, request *generatedRequest, dynam
r.options.Progress.DecrementRequests(1)
return err
}
defer func() {
_, _ = io.CopyN(ioutil.Discard, resp.Body, drainReqSize)
resp.Body.Close()
}()
gologger.Verbose().Msgf("[%s] Sent HTTP request to %s", r.options.TemplateID, formedURL)
r.options.Output.Request(r.options.TemplateID, reqURL, "http", err)
@ -286,8 +289,6 @@ func (r *Request) executeRequest(reqURL string, request *generatedRequest, dynam
dumpedResponseHeaders, err := httputil.DumpResponse(resp, false)
if err != nil {
_, _ = io.CopyN(ioutil.Discard, resp.Body, drainReqSize)
resp.Body.Close()
return errors.Wrap(err, "could not dump http response")
}
@ -299,8 +300,6 @@ func (r *Request) executeRequest(reqURL string, request *generatedRequest, dynam
}
data, err := ioutil.ReadAll(bodyReader)
if err != nil {
_, _ = io.CopyN(ioutil.Discard, resp.Body, drainReqSize)
resp.Body.Close()
return errors.Wrap(err, "could not read http body")
}
resp.Body.Close()
@ -364,8 +363,6 @@ func (r *Request) executeRequest(reqURL string, request *generatedRequest, dynam
return nil
}
const two = 2
// setCustomHeaders sets the custom headers for generated request
func (r *Request) setCustomHeaders(req *generatedRequest) {
for k, v := range r.customHeaders {

View File

@ -26,12 +26,12 @@ func (r *Request) newGenerator() *requestGenerator {
// nextValue returns the next path or the next raw request depending on user input
// It returns false if all the inputs have been exhausted by the generator instance.
func (r *requestGenerator) nextValue() (string, map[string]interface{}, bool) {
func (r *requestGenerator) nextValue() (value string, payloads map[string]interface{}, result bool) {
// If we have paths, return the next path.
if len(r.request.Path) > 0 && r.currentIndex < len(r.request.Path) {
if item := r.request.Path[r.currentIndex]; item != "" {
if value := r.request.Path[r.currentIndex]; value != "" {
r.currentIndex++
return item, nil, true
return value, nil, true
}
}

View File

@ -1,10 +1,8 @@
package http
import (
"bufio"
"bytes"
"compress/gzip"
"io"
"io/ioutil"
"net/http"
"net/http/httputil"
@ -118,26 +116,3 @@ func handleDecompression(resp *http.Response, bodyOrig []byte) (bodyDec []byte,
}
return bodyOrig, nil
}
// rawHasBody checks if a RFC compliant request has the body
func rawHasBody(data string) bool {
b := bufio.NewReader(strings.NewReader(data))
req, err := http.ReadRequest(b)
if err == io.EOF {
return false
}
if err != nil {
return false
}
if req.Body == http.NoBody {
return false
}
// It's enough to read a chunk to check the presence of the body
body, err := ioutil.ReadAll(io.LimitReader(req.Body, 512))
if err != nil {
return false
}
return len(body) > 0
}

View File

@ -69,9 +69,9 @@ func (r *Request) Compile(options *protocols.ExecuterOptions) error {
address = strings.TrimPrefix(address, "tls://")
}
if strings.Contains(address, ":") {
addressHost, addressPort, err := net.SplitHostPort(address)
if err != nil {
return errors.Wrap(err, "could not parse address")
addressHost, addressPort, portErr := net.SplitHostPort(address)
if portErr != nil {
return errors.Wrap(portErr, "could not parse address")
}
r.addresses = append(r.addresses, addressKV{ip: addressHost, port: addressPort, tls: shouldUseTLS})
} else {
@ -83,8 +83,8 @@ func (r *Request) Compile(options *protocols.ExecuterOptions) error {
if input.Type != "" {
continue
}
if compiled, err := expressions.Evaluate(input.Data, map[string]interface{}{}); err == nil {
input.Data = string(compiled)
if compiled, evalErr := expressions.Evaluate(input.Data, map[string]interface{}{}); evalErr == nil {
input.Data = compiled
}
}

View File

@ -62,7 +62,7 @@ func (r *Request) Extract(data map[string]interface{}, extractor *extractors.Ext
}
// responseToDSLMap converts a DNS response to a map for use in DSL matching
func (r *Request) responseToDSLMap(req, resp, raw string, host, matched string) output.InternalEvent {
func (r *Request) responseToDSLMap(req, resp, raw, host, matched string) output.InternalEvent {
data := make(output.InternalEvent, 6)
// Some data regarding the request metadata

View File

@ -60,7 +60,7 @@ func (r *Request) executeAddress(actualAddress, address, input string, shouldUse
err error
)
if host, _, err := net.SplitHostPort(actualAddress); err == nil {
if host, _, splitErr := net.SplitHostPort(actualAddress); splitErr == nil {
hostname = host
}
@ -75,7 +75,7 @@ func (r *Request) executeAddress(actualAddress, address, input string, shouldUse
return errors.Wrap(err, "could not connect to server request")
}
defer conn.Close()
conn.SetReadDeadline(time.Now().Add(time.Duration(r.options.Options.Timeout) * time.Second))
_ = conn.SetReadDeadline(time.Now().Add(time.Duration(r.options.Options.Timeout) * time.Second))
responseBuilder := &strings.Builder{}
reqBuilder := &strings.Builder{}

View File

@ -21,7 +21,7 @@ func TestFindResponses(t *testing.T) {
ID: templateID,
Info: map[string]interface{}{"severity": "low", "name": "test"},
})
executerOpts.Operators = []*operators.Operators{&operators.Operators{}}
executerOpts.Operators = []*operators.Operators{{}}
err := request.Compile(executerOpts)
require.Nil(t, err, "could not compile file request")

View File

@ -23,7 +23,7 @@ func TestResponseToDSLMap(t *testing.T) {
ID: templateID,
Info: map[string]interface{}{"severity": "low", "name": "test"},
})
executerOpts.Operators = []*operators.Operators{&operators.Operators{}}
executerOpts.Operators = []*operators.Operators{{}}
err := request.Compile(executerOpts)
require.Nil(t, err, "could not compile file request")
@ -49,7 +49,7 @@ func TestHTTPOperatorMatch(t *testing.T) {
ID: templateID,
Info: map[string]interface{}{"severity": "low", "name": "test"},
})
executerOpts.Operators = []*operators.Operators{&operators.Operators{}}
executerOpts.Operators = []*operators.Operators{{}}
err := request.Compile(executerOpts)
require.Nil(t, err, "could not compile file request")
@ -115,7 +115,7 @@ func TestHTTPOperatorExtract(t *testing.T) {
ID: templateID,
Info: map[string]interface{}{"severity": "low", "name": "test"},
})
executerOpts.Operators = []*operators.Operators{&operators.Operators{}}
executerOpts.Operators = []*operators.Operators{{}}
err := request.Compile(executerOpts)
require.Nil(t, err, "could not compile file request")
@ -168,7 +168,7 @@ func TestHTTPMakeResult(t *testing.T) {
ID: templateID,
Info: map[string]interface{}{"severity": "low", "name": "test"},
})
executerOpts.Operators = []*operators.Operators{&operators.Operators{
executerOpts.Operators = []*operators.Operators{{
Matchers: []*matchers.Matcher{{
Name: "test",
Part: "body",

View File

@ -17,7 +17,7 @@ func readResponseFromString(data string) (*http.Response, error) {
if lastIndex == -1 {
return nil, errors.New("malformed raw http response")
}
final = data[:] // choose last http/ in case of it being later.
final = data // choose last http/ in case of it being later.
}
return http.ReadResponse(bufio.NewReader(strings.NewReader(final)), nil)
}

View File

@ -2,7 +2,7 @@ package protocols
import (
"github.com/projectdiscovery/nuclei/v2/internal/progress"
"github.com/projectdiscovery/nuclei/v2/pkg/catalogue"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog"
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
"github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors"
"github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers"
@ -44,8 +44,8 @@ type ExecuterOptions struct {
Progress *progress.Progress
// RateLimiter is a rate-limiter for limiting sent number of requests.
RateLimiter ratelimit.Limiter
// Catalogue is a template catalogue implementation for nuclei
Catalogue *catalogue.Catalogue
// Catalog is a template catalog implementation for nuclei
Catalog *catalog.Catalog
// ProjectFile is the project file for nuclei
ProjectFile *projectfile.ProjectFile
// Browser is a browser engine for running headless templates

View File

@ -22,8 +22,6 @@ type Storage struct {
storage *leveldb.DB
}
const storageFilename = "nuclei-events.db"
// New creates a new duplicate detecting storage for nuclei scan events.
func New(dbPath string) (*Storage, error) {
storage := &Storage{}
@ -65,29 +63,29 @@ func (s *Storage) Close() {
func (s *Storage) Index(result *output.ResultEvent) (bool, error) {
hasher := sha1.New()
if result.TemplateID != "" {
hasher.Write(unsafeToBytes(result.TemplateID))
_, _ = hasher.Write(unsafeToBytes(result.TemplateID))
}
if result.MatcherName != "" {
hasher.Write(unsafeToBytes(result.MatcherName))
_, _ = hasher.Write(unsafeToBytes(result.MatcherName))
}
if result.ExtractorName != "" {
hasher.Write(unsafeToBytes(result.ExtractorName))
_, _ = hasher.Write(unsafeToBytes(result.ExtractorName))
}
if result.Type != "" {
hasher.Write(unsafeToBytes(result.Type))
_, _ = hasher.Write(unsafeToBytes(result.Type))
}
if result.Host != "" {
hasher.Write(unsafeToBytes(result.Host))
_, _ = hasher.Write(unsafeToBytes(result.Host))
}
if result.Matched != "" {
hasher.Write(unsafeToBytes(result.Matched))
_, _ = hasher.Write(unsafeToBytes(result.Matched))
}
for _, v := range result.ExtractedResults {
hasher.Write(unsafeToBytes(v))
_, _ = hasher.Write(unsafeToBytes(v))
}
for k, v := range result.Metadata {
hasher.Write(unsafeToBytes(k))
hasher.Write(unsafeToBytes(types.ToString(v)))
_, _ = hasher.Write(unsafeToBytes(k))
_, _ = hasher.Write(unsafeToBytes(types.ToString(v)))
}
hash := hasher.Sum(nil)

View File

@ -10,62 +10,62 @@ import (
)
// Summary returns a formatted built one line summary of the event
func Summary(output *output.ResultEvent) string {
template := GetMatchedTemplate(output)
func Summary(event *output.ResultEvent) string {
template := GetMatchedTemplate(event)
builder := &strings.Builder{}
builder.WriteString("[")
builder.WriteString(template)
builder.WriteString("] [")
builder.WriteString(types.ToString(output.Info["severity"]))
builder.WriteString(types.ToString(event.Info["severity"]))
builder.WriteString("] ")
builder.WriteString(types.ToString(output.Info["name"]))
builder.WriteString(types.ToString(event.Info["name"]))
builder.WriteString(" found on ")
builder.WriteString(output.Host)
builder.WriteString(event.Host)
data := builder.String()
return data
}
// MarkdownDescription formats a short description of the generated
// event by the nuclei scanner in Markdown format.
func MarkdownDescription(output *output.ResultEvent) string {
template := GetMatchedTemplate(output)
func MarkdownDescription(event *output.ResultEvent) string {
template := GetMatchedTemplate(event)
builder := &bytes.Buffer{}
builder.WriteString("**Details**: **")
builder.WriteString(template)
builder.WriteString("** ")
builder.WriteString(" matched at ")
builder.WriteString(output.Host)
builder.WriteString(event.Host)
builder.WriteString("\n\n**Protocol**: ")
builder.WriteString(strings.ToUpper(output.Type))
builder.WriteString(strings.ToUpper(event.Type))
builder.WriteString("\n\n**Full URL**: ")
builder.WriteString(output.Matched)
builder.WriteString(event.Matched)
builder.WriteString("\n\n**Timestamp**: ")
builder.WriteString(output.Timestamp.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
builder.WriteString(event.Timestamp.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
builder.WriteString("\n\n**Template Information**\n\n| Key | Value |\n|---|---|\n")
for k, v := range output.Info {
for k, v := range event.Info {
builder.WriteString(fmt.Sprintf("| %s | %s |\n", k, v))
}
builder.WriteString("\n**Request**\n\n```\n")
builder.WriteString(output.Request)
builder.WriteString(event.Request)
builder.WriteString("\n```\n\n<details><summary>**Response**</summary>\n\n```\n")
builder.WriteString(output.Response)
builder.WriteString(event.Response)
builder.WriteString("\n```\n\n")
if len(output.ExtractedResults) > 0 || len(output.Metadata) > 0 {
if len(event.ExtractedResults) > 0 || len(event.Metadata) > 0 {
builder.WriteString("**Extra Information**\n\n")
if len(output.ExtractedResults) > 0 {
if len(event.ExtractedResults) > 0 {
builder.WriteString("**Extracted results**:\n\n")
for _, v := range output.ExtractedResults {
for _, v := range event.ExtractedResults {
builder.WriteString("- ")
builder.WriteString(v)
builder.WriteString("\n")
}
builder.WriteString("\n")
}
if len(output.Metadata) > 0 {
if len(event.Metadata) > 0 {
builder.WriteString("**Metadata**:\n\n")
for k, v := range output.Metadata {
for k, v := range event.Metadata {
builder.WriteString("- ")
builder.WriteString(k)
builder.WriteString(": ")
@ -80,16 +80,16 @@ func MarkdownDescription(output *output.ResultEvent) string {
}
// GetMatchedTemplate returns the matched template from a result event
func GetMatchedTemplate(output *output.ResultEvent) string {
func GetMatchedTemplate(event *output.ResultEvent) string {
builder := &strings.Builder{}
builder.WriteString(output.TemplateID)
if output.MatcherName != "" {
builder.WriteString(event.TemplateID)
if event.MatcherName != "" {
builder.WriteString(":")
builder.WriteString(output.MatcherName)
builder.WriteString(event.MatcherName)
}
if output.ExtractorName != "" {
if event.ExtractorName != "" {
builder.WriteString(":")
builder.WriteString(output.ExtractorName)
builder.WriteString(event.ExtractorName)
}
template := builder.String()
return template

View File

@ -53,10 +53,7 @@ func (f *Filter) Compile() {
func (f *Filter) GetMatch(event *output.ResultEvent) bool {
severity := types.ToString(event.Info["severity"])
if len(f.severity) > 0 {
if stringSliceContains(f.severity, severity) {
return true
}
return false
return stringSliceContains(f.severity, severity)
}
tags := event.Info["tags"]
@ -94,8 +91,8 @@ func New(config, db string) (*Client, error) {
defer file.Close()
options := &Options{}
if err := yaml.NewDecoder(file).Decode(options); err != nil {
return nil, err
if parseErr := yaml.NewDecoder(file).Decode(options); parseErr != nil {
return nil, parseErr
}
if options.AllowList != nil {
options.AllowList.Compile()
@ -143,7 +140,7 @@ func (c *Client) CreateIssue(event *output.ResultEvent) error {
found, err := c.dedupe.Index(event)
if err != nil {
c.tracker.CreateIssue(event)
_ = c.tracker.CreateIssue(event)
return err
}
if found {

View File

@ -75,45 +75,45 @@ func (i *Integration) CreateIssue(event *output.ResultEvent) error {
// jiraFormatDescription formats a short description of the generated
// event by the nuclei scanner in Jira format.
func jiraFormatDescription(output *output.ResultEvent) string {
template := format.GetMatchedTemplate(output)
func jiraFormatDescription(event *output.ResultEvent) string {
template := format.GetMatchedTemplate(event)
builder := &bytes.Buffer{}
builder.WriteString("*Details*: *")
builder.WriteString(template)
builder.WriteString("* ")
builder.WriteString(" matched at ")
builder.WriteString(output.Host)
builder.WriteString(event.Host)
builder.WriteString("\n\n*Protocol*: ")
builder.WriteString(strings.ToUpper(output.Type))
builder.WriteString(strings.ToUpper(event.Type))
builder.WriteString("\n\n*Full URL*: ")
builder.WriteString(output.Matched)
builder.WriteString(event.Matched)
builder.WriteString("\n\n*Timestamp*: ")
builder.WriteString(output.Timestamp.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
builder.WriteString(event.Timestamp.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
builder.WriteString("\n\n*Template Information*\n\n| Key | Value |\n")
for k, v := range output.Info {
for k, v := range event.Info {
builder.WriteString(fmt.Sprintf("| %s | %s |\n", k, v))
}
builder.WriteString("\n*Request*\n\n{code}\n")
builder.WriteString(output.Request)
builder.WriteString(event.Request)
builder.WriteString("\n{code}\n\n*Response*\n\n{code}\n")
builder.WriteString(output.Response)
builder.WriteString(event.Response)
builder.WriteString("\n{code}\n\n")
if len(output.ExtractedResults) > 0 || len(output.Metadata) > 0 {
if len(event.ExtractedResults) > 0 || len(event.Metadata) > 0 {
builder.WriteString("*Extra Information*\n\n")
if len(output.ExtractedResults) > 0 {
if len(event.ExtractedResults) > 0 {
builder.WriteString("*Extracted results*:\n\n")
for _, v := range output.ExtractedResults {
for _, v := range event.ExtractedResults {
builder.WriteString("- ")
builder.WriteString(v)
builder.WriteString("\n")
}
builder.WriteString("\n")
}
if len(output.Metadata) > 0 {
if len(event.Metadata) > 0 {
builder.WriteString("*Metadata*:\n\n")
for k, v := range output.Metadata {
for k, v := range event.Metadata {
builder.WriteString("- ")
builder.WriteString(k)
builder.WriteString(": ")

View File

@ -18,6 +18,7 @@ import (
)
// Parse parses a yaml request template file
//nolint:gocritic // this cannot be passed by pointer
func Parse(filePath string, options protocols.ExecuterOptions) (*Template, error) {
template := &Template{}
@ -84,12 +85,12 @@ func Parse(filePath string, options protocols.ExecuterOptions) (*Template, error
}
if len(template.RequestsHTTP) > 0 {
if options.Options.OfflineHTTP {
operators := []*operators.Operators{}
operatorsList := []*operators.Operators{}
for _, req := range template.RequestsHTTP {
operators = append(operators, &req.Operators)
operatorsList = append(operatorsList, &req.Operators)
}
options.Operators = operators
options.Operators = operatorsList
template.Executer = executer.NewExecuter([]protocols.Request{&offlinehttp.Request{}}, &options)
} else {
for _, req := range template.RequestsHTTP {
@ -130,8 +131,8 @@ func Parse(filePath string, options protocols.ExecuterOptions) (*Template, error
}
// compileWorkflow compiles the workflow for execution
func (t *Template) compileWorkflow(options *protocols.ExecuterOptions, workflows *workflows.Workflow) error {
for _, workflow := range workflows.Workflows {
func (t *Template) compileWorkflow(options *protocols.ExecuterOptions, workflow *workflows.Workflow) error {
for _, workflow := range workflow.Workflows {
if err := t.parseWorkflow(workflow, options); err != nil {
return err
}
@ -161,7 +162,7 @@ func (t *Template) parseWorkflow(workflow *workflows.WorkflowTemplate, options *
// parseWorkflowTemplate parses a workflow template creating an executer
func (t *Template) parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, options *protocols.ExecuterOptions) error {
paths, err := options.Catalogue.GetTemplatePath(workflow.Template)
paths, err := options.Catalog.GetTemplatePath(workflow.Template)
if err != nil {
return errors.Wrap(err, "could not get workflow template")
}
@ -170,7 +171,7 @@ func (t *Template) parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, o
Output: options.Output,
Options: options.Options,
Progress: options.Progress,
Catalogue: options.Catalogue,
Catalog: options.Catalog,
RateLimiter: options.RateLimiter,
IssuesClient: options.IssuesClient,
ProjectFile: options.ProjectFile,
@ -220,9 +221,7 @@ mainLoop:
}
// getKeyValue returns key value pair for a data string
func getKeyValue(data string) (string, string) {
var key, value string
func getKeyValue(data string) (key, value string) {
if strings.Contains(data, ":") {
parts := strings.SplitN(data, ":", 2)
if len(parts) == 2 {

View File

@ -34,7 +34,7 @@ func ToString(data interface{}) string {
case uint:
return strconv.FormatUint(uint64(s), 10)
case uint64:
return strconv.FormatUint(uint64(s), 10)
return strconv.FormatUint(s, 10)
case uint32:
return strconv.FormatUint(uint64(s), 10)
case uint16:

View File

@ -4,6 +4,69 @@ import "github.com/projectdiscovery/goflags"
// Options contains the configuration options for nuclei scanner.
type Options struct {
// Tags contains a list of tags to execute templates for. Multiple paths
// can be specified with -l flag and -tags can be used in combination with
// the -l flag.
Tags goflags.StringSlice
// Templates specifies the template/templates to use
Templates goflags.StringSlice
// ExcludedTemplates specifies the template/templates to exclude
ExcludedTemplates goflags.StringSlice
// CustomHeaders is the list of custom global headers to send with each request.
CustomHeaders goflags.StringSlice
// Severity filters templates based on their severity and only run the matching ones.
Severity goflags.StringSlice
InternalResolversList []string // normalized from resolvers flag as well as file provided.
// BurpCollaboratorBiid is the Burp Collaborator BIID for polling interactions.
BurpCollaboratorBiid string
// ProjectPath allows nuclei to use a user defined project folder
ProjectPath string
// Target is a single URL/Domain to scan using a template
Target string
// Targets specifies the targets to scan using templates.
Targets string
// Output is the file to write found results to.
Output string
// ProxyURL is the URL for the proxy server
ProxyURL string
// ProxySocksURL is the URL for the proxy socks server
ProxySocksURL string
// TemplatesDirectory is the directory to use for storing templates
TemplatesDirectory string
// TraceLogFile specifies a file to write with the trace of all requests
TraceLogFile string
// ReportingDB is the db for report storage as well as deduplication
ReportingDB string
// ReportingConfig is the config file for nuclei reporting module
ReportingConfig string
// ResolversFile is a file containing resolvers for nuclei.
ResolversFile string
// StatsInterval is the number of seconds to display stats after
StatsInterval int
// MetricsPort is the port to show metrics on
MetricsPort int
// BulkSize is the of targets analyzed in parallel for each template
BulkSize int
// TemplateThreads is the number of templates executed in parallel
TemplateThreads int
// Timeout is the seconds to wait for a response from the server.
Timeout int
// Retries is the number of times to retry the request
Retries int
// Rate-Limit is the maximum number of requests per specified target
RateLimit int
// OfflineHTTP is a flag that specific offline processing of http response
// using same matchers/extractors from http protocol without the need
// to send a new request, reading responses from a file.
OfflineHTTP bool
// Headless specifies whether to allow headless mode templates
Headless bool
// ShowBrowser specifies whether the show the browser in headless mode
ShowBrowser bool
// Workflows specifies if only to execute workflows (no normal templates will be run)
Workflows bool
// SytemResolvers enables override of nuclei's DNS client opting to use system resolver stack.
SystemResolvers bool
// RandomAgent generates random User-Agent
RandomAgent bool
// Metrics enables display of metrics via an http endpoint
@ -42,68 +105,4 @@ type Options struct {
NoMeta bool
// Project is used to avoid sending same HTTP request multiple times
Project bool
// MetricsPort is the port to show metrics on
MetricsPort int
// BulkSize is the of targets analyzed in parallel for each template
BulkSize int
// TemplateThreads is the number of templates executed in parallel
TemplateThreads int
// Timeout is the seconds to wait for a response from the server.
Timeout int
// Retries is the number of times to retry the request
Retries int
// Rate-Limit is the maximum number of requests per specified target
RateLimit int
// BurpCollaboratorBiid is the Burp Collaborator BIID for polling interactions.
BurpCollaboratorBiid string
// ProjectPath allows nuclei to use a user defined project folder
ProjectPath string
// Severity filters templates based on their severity and only run the matching ones.
Severity goflags.StringSlice
// Target is a single URL/Domain to scan using a template
Target string
// Targets specifies the targets to scan using templates.
Targets string
// Output is the file to write found results to.
Output string
// ProxyURL is the URL for the proxy server
ProxyURL string
// ProxySocksURL is the URL for the proxy socks server
ProxySocksURL string
// TemplatesDirectory is the directory to use for storing templates
TemplatesDirectory string
// TraceLogFile specifies a file to write with the trace of all requests
TraceLogFile string
// Templates specifies the template/templates to use
Templates goflags.StringSlice
// ExcludedTemplates specifies the template/templates to exclude
ExcludedTemplates goflags.StringSlice
// CustomHeaders is the list of custom global headers to send with each request.
CustomHeaders goflags.StringSlice
// ReportingDB is the db for report storage as well as deduplication
ReportingDB string
// ReportingConfig is the config file for nuclei reporting module
ReportingConfig string
// Tags contains a list of tags to execute templates for. Multiple paths
// can be specified with -l flag and -tags can be used in combination with
// the -l flag.
Tags goflags.StringSlice
// OfflineHTTP is a flag that specific offline processing of http response
// using same matchers/extractors from http protocol without the need
// to send a new request, reading responses from a file.
OfflineHTTP bool
// ResolversFile is a file containing resolvers for nuclei.
ResolversFile string
// Headless specifies whether to allow headless mode templates
Headless bool
// ShowBrowser specifies whether the show the browser in headless mode
ShowBrowser bool
// Workflows specifies if only to execute workflows (no normal templates will be run)
Workflows bool
// StatsInterval is the number of seconds to display stats after
StatsInterval int
// SytemResolvers enables override of nuclei's DNS client opting to use system resolver stack.
SystemResolvers bool
InternalResolversList []string // normalized from resolvers flag as well as file provided.
}

View File

@ -12,11 +12,11 @@ import (
)
func TestWorkflowsSimple(t *testing.T) {
progress, _ := progress.NewProgress(0, false, false, 0)
progressBar, _ := progress.NewProgress(0, false, false, 0)
workflow := &Workflow{Options: &protocols.ExecuterOptions{Options: &types.Options{TemplateThreads: 10}}, Workflows: []*WorkflowTemplate{
{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true}, Options: &protocols.ExecuterOptions{Progress: progress}},
Executer: &mockExecuter{result: true}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}},
}}
@ -25,19 +25,19 @@ func TestWorkflowsSimple(t *testing.T) {
}
func TestWorkflowsSimpleMultiple(t *testing.T) {
progress, _ := progress.NewProgress(0, false, false, 0)
progressBar, _ := progress.NewProgress(0, false, false, 0)
var firstInput, secondInput string
workflow := &Workflow{Options: &protocols.ExecuterOptions{Options: &types.Options{TemplateThreads: 10}}, Workflows: []*WorkflowTemplate{
{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true, executeHook: func(input string) {
firstInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}},
{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true, executeHook: func(input string) {
secondInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}},
}}
@ -49,18 +49,18 @@ func TestWorkflowsSimpleMultiple(t *testing.T) {
}
func TestWorkflowsSubtemplates(t *testing.T) {
progress, _ := progress.NewProgress(0, false, false, 0)
progressBar, _ := progress.NewProgress(0, false, false, 0)
var firstInput, secondInput string
workflow := &Workflow{Options: &protocols.ExecuterOptions{Options: &types.Options{TemplateThreads: 10}}, Workflows: []*WorkflowTemplate{
{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true, executeHook: func(input string) {
firstInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}, Subtemplates: []*WorkflowTemplate{{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true, executeHook: func(input string) {
secondInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}}}},
}}
@ -72,18 +72,18 @@ func TestWorkflowsSubtemplates(t *testing.T) {
}
func TestWorkflowsSubtemplatesNoMatch(t *testing.T) {
progress, _ := progress.NewProgress(0, false, false, 0)
progressBar, _ := progress.NewProgress(0, false, false, 0)
var firstInput, secondInput string
workflow := &Workflow{Options: &protocols.ExecuterOptions{Options: &types.Options{TemplateThreads: 10}}, Workflows: []*WorkflowTemplate{
{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: false, executeHook: func(input string) {
firstInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}, Subtemplates: []*WorkflowTemplate{{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true, executeHook: func(input string) {
secondInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}}}},
}}
@ -95,7 +95,7 @@ func TestWorkflowsSubtemplatesNoMatch(t *testing.T) {
}
func TestWorkflowsSubtemplatesWithMatcher(t *testing.T) {
progress, _ := progress.NewProgress(0, false, false, 0)
progressBar, _ := progress.NewProgress(0, false, false, 0)
var firstInput, secondInput string
workflow := &Workflow{Options: &protocols.ExecuterOptions{Options: &types.Options{TemplateThreads: 10}}, Workflows: []*WorkflowTemplate{
@ -107,11 +107,11 @@ func TestWorkflowsSubtemplatesWithMatcher(t *testing.T) {
Matches: map[string]struct{}{"tomcat": {}},
Extracts: map[string][]string{},
}},
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}, Matchers: []*Matcher{{Name: "tomcat", Subtemplates: []*WorkflowTemplate{{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true, executeHook: func(input string) {
secondInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}}}}}},
}}
@ -123,7 +123,7 @@ func TestWorkflowsSubtemplatesWithMatcher(t *testing.T) {
}
func TestWorkflowsSubtemplatesWithMatcherNoMatch(t *testing.T) {
progress, _ := progress.NewProgress(0, false, false, 0)
progressBar, _ := progress.NewProgress(0, false, false, 0)
var firstInput, secondInput string
workflow := &Workflow{Options: &protocols.ExecuterOptions{Options: &types.Options{TemplateThreads: 10}}, Workflows: []*WorkflowTemplate{
@ -135,11 +135,11 @@ func TestWorkflowsSubtemplatesWithMatcherNoMatch(t *testing.T) {
Matches: map[string]struct{}{"tomcat": {}},
Extracts: map[string][]string{},
}},
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}, Matchers: []*Matcher{{Name: "apache", Subtemplates: []*WorkflowTemplate{{Executers: []*ProtocolExecuterPair{{
Executer: &mockExecuter{result: true, executeHook: func(input string) {
secondInput = input
}}, Options: &protocols.ExecuterOptions{Progress: progress}},
}}, Options: &protocols.ExecuterOptions{Progress: progressBar}},
}}}}}},
}}