mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-22 12:35:29 +00:00
merged master
This commit is contained in:
commit
c2433fdb34
@ -12,7 +12,7 @@ import (
|
|||||||
// the template requesting process.
|
// the template requesting process.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Debug bool // Debug mode allows debugging request/responses for the engine
|
Debug bool // Debug mode allows debugging request/responses for the engine
|
||||||
Templates string // Signature specifies the template/templates to use
|
Templates multiStringFlag // Signature specifies the template/templates to use
|
||||||
Target string // Target is a single URL/Domain to scan usng a template
|
Target string // Target is a single URL/Domain to scan usng a template
|
||||||
Targets string // Targets specifies the targets to scan using templates.
|
Targets string // Targets specifies the targets to scan using templates.
|
||||||
Threads int // Thread controls the number of concurrent requests to make.
|
Threads int // Thread controls the number of concurrent requests to make.
|
||||||
@ -33,12 +33,23 @@ type Options struct {
|
|||||||
Stdin bool // Stdin specifies whether stdin input was given to the process
|
Stdin bool // Stdin specifies whether stdin input was given to the process
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type multiStringFlag []string
|
||||||
|
|
||||||
|
func (m *multiStringFlag) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiStringFlag) Set(value string) error {
|
||||||
|
*m = append(*m, value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseOptions parses the command line flags provided by a user
|
// ParseOptions parses the command line flags provided by a user
|
||||||
func ParseOptions() *Options {
|
func ParseOptions() *Options {
|
||||||
options := &Options{}
|
options := &Options{}
|
||||||
|
|
||||||
flag.StringVar(&options.Target, "target", "", "Target is a single target to scan using template")
|
flag.StringVar(&options.Target, "target", "", "Target is a single target to scan using template")
|
||||||
flag.StringVar(&options.Templates, "t", "", "Template input file/files to run on host")
|
flag.Var(&options.Templates, "t","Template input file/files to run on host. Can be used multiple times.")
|
||||||
flag.StringVar(&options.Targets, "l", "", "List of URLs to run templates on")
|
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.Output, "o", "", "File to write output to (optional)")
|
||||||
flag.StringVar(&options.ProxyURL, "proxy-url", "", "URL of the proxy server")
|
flag.StringVar(&options.ProxyURL, "proxy-url", "", "URL of the proxy server")
|
||||||
|
|||||||
@ -44,7 +44,7 @@ func New(options *Options) (*Runner, error) {
|
|||||||
if err := runner.updateTemplates(); err != nil {
|
if err := runner.updateTemplates(); err != nil {
|
||||||
gologger.Warningf("Could not update templates: %s\n", err)
|
gologger.Warningf("Could not update templates: %s\n", err)
|
||||||
}
|
}
|
||||||
if (options.Templates == "" || (options.Targets == "" && !options.Stdin && options.Target == "")) && options.UpdateTemplates {
|
if (len(options.Templates) == 0 || (options.Targets == "" && !options.Stdin && options.Target == "")) && options.UpdateTemplates {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,66 +88,79 @@ func (r *Runner) Close() {
|
|||||||
os.Remove(r.tempFile)
|
os.Remove(r.tempFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isFilePath(path string) (bool, error) {
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return info.Mode().IsRegular(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) resolvePathIfRelative(path string) (string, error) {
|
||||||
|
if r.isRelative(path) {
|
||||||
|
newPath, err := r.resolvePath(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return newPath, nil
|
||||||
|
}
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNewPath(path string, pathMap map[string]bool) bool {
|
||||||
|
if _, already := pathMap[path]; already {
|
||||||
|
gologger.Warningf("Skipping already specified path '%s'", path)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// RunEnumeration sets up the input layer for giving input nuclei.
|
// RunEnumeration sets up the input layer for giving input nuclei.
|
||||||
// binary and runs the actual enumeration
|
// binary and runs the actual enumeration
|
||||||
func (r *Runner) RunEnumeration() {
|
func (r *Runner) RunEnumeration() {
|
||||||
var err error
|
// keeps track of processed dirs and files
|
||||||
|
processed := make(map[string]bool)
|
||||||
|
allTemplates := []string{}
|
||||||
|
|
||||||
// Check if the template is an absolute path or relative path.
|
// parses user input, handle file/directory cases and produce a list of unique templates
|
||||||
// If the path is absolute, use it. Otherwise,
|
for _, t := range r.options.Templates {
|
||||||
if r.isRelative(r.options.Templates) {
|
// resolve and convert relative to absolute path
|
||||||
newPath, err := r.resolvePath(r.options.Templates)
|
absPath, err := r.resolvePathIfRelative(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gologger.Errorf("Could not find template file '%s': %s\n", r.options.Templates, err)
|
gologger.Errorf("Could not find template file '%s': %s\n", t, err)
|
||||||
return
|
continue
|
||||||
}
|
|
||||||
r.options.Templates = newPath
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single yaml provided
|
// determine file/directory
|
||||||
if strings.HasSuffix(r.options.Templates, ".yaml") {
|
isFile, err := isFilePath(absPath)
|
||||||
t, err := r.parse(r.options.Templates)
|
if err != nil {
|
||||||
switch t.(type) {
|
gologger.Errorf("Could not stat '%s': %s\n", absPath, err)
|
||||||
case *templates.Template:
|
continue
|
||||||
var results bool
|
|
||||||
template := t.(*templates.Template)
|
|
||||||
// process http requests
|
|
||||||
for _, request := range template.BulkRequestsHTTP {
|
|
||||||
results = r.processTemplateRequest(template, request)
|
|
||||||
}
|
|
||||||
// process dns requests
|
|
||||||
for _, request := range template.RequestsDNS {
|
|
||||||
dnsResults := r.processTemplateRequest(template, request)
|
|
||||||
if !results {
|
|
||||||
results = dnsResults
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !results {
|
// test for uniqueness
|
||||||
if r.output != nil {
|
if !isNewPath(absPath, processed) {
|
||||||
outputFile := r.output.Name()
|
continue
|
||||||
r.output.Close()
|
|
||||||
os.Remove(outputFile)
|
|
||||||
}
|
|
||||||
gologger.Infof("No results found for the template. Happy hacking!")
|
|
||||||
}
|
|
||||||
case *workflows.Workflow:
|
|
||||||
workflow := t.(*workflows.Workflow)
|
|
||||||
r.ProcessWorkflowWithList(workflow)
|
|
||||||
default:
|
|
||||||
gologger.Errorf("Could not parse file '%s': %s\n", r.options.Templates, err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the template passed is a directory
|
// mark this absolute path as processed
|
||||||
|
// - if it's a file, we'll never process it again
|
||||||
|
// - if it's a dir, we'll never walk it again
|
||||||
|
processed[absPath] = true
|
||||||
|
|
||||||
|
if isFile {
|
||||||
|
allTemplates = append(allTemplates, absPath)
|
||||||
|
} else {
|
||||||
matches := []string{}
|
matches := []string{}
|
||||||
|
|
||||||
// Recursively walk down the Templates directory and run all the template file checks
|
// Recursively walk down the Templates directory and run all the template file checks
|
||||||
err = godirwalk.Walk(r.options.Templates, &godirwalk.Options{
|
err = godirwalk.Walk(absPath, &godirwalk.Options{
|
||||||
Callback: func(path string, d *godirwalk.Dirent) error {
|
Callback: func(path string, d *godirwalk.Dirent) error {
|
||||||
if !d.IsDir() && strings.HasSuffix(path, ".yaml") {
|
if !d.IsDir() && strings.HasSuffix(path, ".yaml") {
|
||||||
|
if isNewPath(path, processed) {
|
||||||
matches = append(matches, path)
|
matches = append(matches, path)
|
||||||
|
processed[path] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -156,16 +169,31 @@ func (r *Runner) RunEnumeration() {
|
|||||||
},
|
},
|
||||||
Unsorted: true,
|
Unsorted: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// directory couldn't be walked
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gologger.Fatalf("Could not find templates in directory '%s': %s\n", r.options.Templates, err)
|
gologger.Labelf("Could not find templates in directory '%s': %s\n", absPath, err)
|
||||||
}
|
continue
|
||||||
// 0 matches means no templates were found in directory
|
|
||||||
if len(matches) == 0 {
|
|
||||||
gologger.Fatalf("Error, no templates found in directory: '%s'\n", r.options.Templates)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// couldn't find templates in directory
|
||||||
|
if len(matches) == 0 {
|
||||||
|
gologger.Labelf("Error, no templates were found in '%s'.\n", absPath)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
allTemplates = append(allTemplates, matches...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 matches means no templates were found in directory
|
||||||
|
if len(allTemplates) == 0 {
|
||||||
|
gologger.Fatalf("Error, no templates were found.\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// run with the specified templates
|
||||||
var results bool
|
var results bool
|
||||||
for _, match := range matches {
|
for _, match := range allTemplates {
|
||||||
t, err := r.parse(match)
|
t, err := r.parse(match)
|
||||||
switch t.(type) {
|
switch t.(type) {
|
||||||
case *templates.Template:
|
case *templates.Template:
|
||||||
@ -195,7 +223,7 @@ func (r *Runner) RunEnumeration() {
|
|||||||
r.output.Close()
|
r.output.Close()
|
||||||
os.Remove(outputFile)
|
os.Remove(outputFile)
|
||||||
}
|
}
|
||||||
gologger.Infof("No results found for the template. Happy hacking!")
|
gologger.Infof("No results found. Happy hacking!")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ func (options *Options) validateOptions() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if a list of templates was provided and it exists
|
// Check if a list of templates was provided and it exists
|
||||||
if options.Templates == "" && !options.UpdateTemplates {
|
if len(options.Templates) == 0 && !options.UpdateTemplates {
|
||||||
return errors.New("no template/templates provided")
|
return errors.New("no template/templates provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user