From c6df7fbd43b37c0502fc7ee64b12a48ee3a3e43d Mon Sep 17 00:00:00 2001 From: Manuel Bua Date: Sun, 2 Aug 2020 13:49:16 +0200 Subject: [PATCH 1/2] Refactor template resolution logic for reusability --- v2/internal/runner/runner.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/v2/internal/runner/runner.go b/v2/internal/runner/runner.go index c675c20d3..d70902886 100644 --- a/v2/internal/runner/runner.go +++ b/v2/internal/runner/runner.go @@ -189,15 +189,14 @@ func isNewPath(path string, pathMap map[string]bool) bool { return true } -// RunEnumeration sets up the input layer for giving input nuclei. -// binary and runs the actual enumeration -func (r *Runner) RunEnumeration() { +// getTemplatesFor parses the specified input template definitions and returns a list of unique, absolute template paths. +func (r *Runner) getTemplatesFor(definitions []string) []string { // keeps track of processed dirs and files processed := make(map[string]bool) allTemplates := []string{} // parses user input, handle file/directory cases and produce a list of unique templates - for _, t := range r.options.Templates { + for _, t := range definitions { var absPath string var err error @@ -293,6 +292,15 @@ func (r *Runner) RunEnumeration() { } } + return allTemplates +} + +// RunEnumeration sets up the input layer for giving input nuclei. +// binary and runs the actual enumeration +func (r *Runner) RunEnumeration() { + // resolves input templates + allTemplates := r.getTemplatesFor(r.options.Templates) + // 0 matches means no templates were found in directory if len(allTemplates) == 0 { gologger.Fatalf("Error, no templates were found.\n") From 4a355f0fc0fc1093d5656732a7dd02a4a2bda9fc Mon Sep 17 00:00:00 2001 From: Manuel Bua Date: Sun, 2 Aug 2020 15:48:10 +0200 Subject: [PATCH 2/2] Add support for template exclusions --- v2/internal/runner/options.go | 4 +++- v2/internal/runner/runner.go | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/v2/internal/runner/options.go b/v2/internal/runner/options.go index b7e9462ce..db746b053 100644 --- a/v2/internal/runner/options.go +++ b/v2/internal/runner/options.go @@ -13,6 +13,7 @@ import ( type Options struct { Debug bool // Debug mode allows debugging request/responses for the engine Templates multiStringFlag // Signature specifies the template/templates to use + ExcludedTemplates multiStringFlag // Signature specifies the template/templates to exclude Target string // Target is a single URL/Domain to scan usng a template Targets string // Targets specifies the targets to scan using templates. Threads int // Thread controls the number of concurrent requests to make. @@ -51,7 +52,8 @@ func ParseOptions() *Options { options := &Options{} flag.StringVar(&options.Target, "target", "", "Target is a single target to scan using template") - flag.Var(&options.Templates, "t", "Template input file/files to run on host. Can be used multiple times.") + flag.Var(&options.Templates, "t", "Template input dir/file/files to run on host. Can be used multiple times. Supports globbing.") + flag.Var(&options.ExcludedTemplates, "exclude", "Template input dir/file/files to exclude. Can be used multiple times. Supports globbing.") flag.StringVar(&options.Targets, "l", "", "List of URLs to run templates on") flag.StringVar(&options.Output, "o", "", "File to write output to (optional)") flag.StringVar(&options.ProxyURL, "proxy-url", "", "URL of the proxy server") diff --git a/v2/internal/runner/runner.go b/v2/internal/runner/runner.go index d70902886..5c4bd7111 100644 --- a/v2/internal/runner/runner.go +++ b/v2/internal/runner/runner.go @@ -298,8 +298,26 @@ func (r *Runner) getTemplatesFor(definitions []string) []string { // RunEnumeration sets up the input layer for giving input nuclei. // binary and runs the actual enumeration func (r *Runner) RunEnumeration() { - // resolves input templates - allTemplates := r.getTemplatesFor(r.options.Templates) + // resolves input templates definitions and any optional exclusion + includedTemplates := r.getTemplatesFor(r.options.Templates) + excludedTemplates := r.getTemplatesFor(r.options.ExcludedTemplates) + // defaults to all templates + allTemplates := includedTemplates + if len(excludedTemplates) > 0 { + excludedMap := make(map[string]struct{}, len(excludedTemplates)) + for _, excl := range excludedTemplates { + excludedMap[excl] = struct{}{} + } + // rebuild list with only non-excluded templates + allTemplates = []string{} + for _, incl := range includedTemplates { + if _, found := excludedMap[incl]; !found { + allTemplates = append(allTemplates, incl) + } else { + gologger.Warningf("Excluding '%s'", incl) + } + } + } // 0 matches means no templates were found in directory if len(allTemplates) == 0 {