mirror of https://github.com/daffainfo/nuclei.git
uniformed template loading
parent
226cb23c97
commit
d3ceb76585
|
@ -27,7 +27,6 @@ type Options struct {
|
|||
CustomHeaders requests.CustomHeaders // Custom global headers
|
||||
UpdateTemplates bool // UpdateTemplates updates the templates installed at startup
|
||||
TemplatesDirectory string // TemplatesDirectory is the directory to use for storing templates
|
||||
WorkflowFile string // Workflow file - experimental support for one workflow file
|
||||
|
||||
Stdin bool // Stdin specifies whether stdin input was given to the process
|
||||
}
|
||||
|
@ -52,7 +51,6 @@ func ParseOptions() *Options {
|
|||
flag.BoolVar(&options.Debug, "debug", false, "Allow debugging of request/responses")
|
||||
flag.BoolVar(&options.UpdateTemplates, "update-templates", false, "Update Templates updates the installed templates (optional)")
|
||||
flag.StringVar(&options.TemplatesDirectory, "templates-directory", "", "Directory to use for storing nuclei-templates")
|
||||
flag.StringVar(&options.WorkflowFile, "workflow-file", "", "workflow-file")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
|
|
|
@ -80,47 +80,39 @@ func (r *Runner) Close() {
|
|||
// RunEnumeration sets up the input layer for giving input nuclei.
|
||||
// binary and runs the actual enumeration
|
||||
func (r *Runner) RunEnumeration() {
|
||||
// handles a single workflow
|
||||
if r.options.WorkflowFile != "" {
|
||||
workflow, err := workflows.Parse(r.options.WorkflowFile)
|
||||
if err != nil {
|
||||
gologger.Errorf("Could not parse workflow file '%s': %s\n", r.options.WorkflowFile, err)
|
||||
return
|
||||
}
|
||||
r.ProcessWorkflowWithList(workflow)
|
||||
return
|
||||
}
|
||||
|
||||
// If the template path is a single template and not a glob, use that.
|
||||
// Single yaml provided
|
||||
if !strings.Contains(r.options.Templates, "*") && strings.HasSuffix(r.options.Templates, ".yaml") {
|
||||
template, err := templates.ParseTemplate(r.options.Templates)
|
||||
if err != nil {
|
||||
gologger.Errorf("Could not parse template file '%s': %s\n", r.options.Templates, err)
|
||||
return
|
||||
}
|
||||
|
||||
// process http requests
|
||||
var results bool
|
||||
for _, request := range template.RequestsHTTP {
|
||||
results = r.processTemplateRequest(template, request)
|
||||
}
|
||||
// process dns requests
|
||||
for _, request := range template.RequestsDNS {
|
||||
dnsResults := r.processTemplateRequest(template, request)
|
||||
t := r.parse(r.options.Templates)
|
||||
switch t.(type) {
|
||||
case *templates.Template:
|
||||
results := false
|
||||
template := t.(*templates.Template)
|
||||
for _, request := range template.RequestsHTTP {
|
||||
results = r.processTemplateRequest(template, request)
|
||||
}
|
||||
for _, request := range template.RequestsDNS {
|
||||
dnsResults := r.processTemplateRequest(template, request)
|
||||
if !results {
|
||||
results = dnsResults
|
||||
}
|
||||
}
|
||||
if !results {
|
||||
results = dnsResults
|
||||
if r.output != nil {
|
||||
outputFile := r.output.Name()
|
||||
r.output.Close()
|
||||
os.Remove(outputFile)
|
||||
}
|
||||
gologger.Infof("No results found for the template. Happy hacking!")
|
||||
}
|
||||
}
|
||||
if !results {
|
||||
if r.output != nil {
|
||||
outputFile := r.output.Name()
|
||||
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'\n", r.options.Templates)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If the template path is glob
|
||||
if strings.Contains(r.options.Templates, "*") {
|
||||
// Handle the glob, evaluate it and run all the template file checks
|
||||
|
@ -131,22 +123,27 @@ func (r *Runner) RunEnumeration() {
|
|||
|
||||
var results bool
|
||||
for _, match := range matches {
|
||||
template, err := templates.ParseTemplate(match)
|
||||
if err != nil {
|
||||
gologger.Errorf("Could not parse template file '%s': %s\n", match, err)
|
||||
return
|
||||
}
|
||||
for _, request := range template.RequestsDNS {
|
||||
dnsResults := r.processTemplateRequest(template, request)
|
||||
if dnsResults {
|
||||
results = dnsResults
|
||||
t := r.parse(match)
|
||||
switch t.(type) {
|
||||
case *templates.Template:
|
||||
template := t.(*templates.Template)
|
||||
for _, request := range template.RequestsDNS {
|
||||
dnsResults := r.processTemplateRequest(template, request)
|
||||
if dnsResults {
|
||||
results = dnsResults
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, request := range template.RequestsHTTP {
|
||||
httpResults := r.processTemplateRequest(template, request)
|
||||
if httpResults {
|
||||
results = httpResults
|
||||
for _, request := range template.RequestsHTTP {
|
||||
httpResults := r.processTemplateRequest(template, request)
|
||||
if httpResults {
|
||||
results = httpResults
|
||||
}
|
||||
}
|
||||
case *workflows.Workflow:
|
||||
workflow := t.(*workflows.Workflow)
|
||||
r.ProcessWorkflowWithList(workflow)
|
||||
default:
|
||||
gologger.Errorf("Could not parse file '%s'\n", r.options.Templates)
|
||||
}
|
||||
}
|
||||
if !results {
|
||||
|
@ -183,22 +180,28 @@ func (r *Runner) RunEnumeration() {
|
|||
}
|
||||
var results bool
|
||||
for _, match := range matches {
|
||||
template, err := templates.ParseTemplate(match)
|
||||
if err != nil {
|
||||
gologger.Errorf("Could not parse template file '%s': %s\n", match, err)
|
||||
return
|
||||
}
|
||||
for _, request := range template.RequestsDNS {
|
||||
dnsResults := r.processTemplateRequest(template, request)
|
||||
if dnsResults {
|
||||
results = dnsResults
|
||||
t := r.parse(match)
|
||||
switch t.(type) {
|
||||
case *templates.Template:
|
||||
template := t.(*templates.Template)
|
||||
|
||||
for _, request := range template.RequestsDNS {
|
||||
dnsResults := r.processTemplateRequest(template, request)
|
||||
if dnsResults {
|
||||
results = dnsResults
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, request := range template.RequestsHTTP {
|
||||
httpResults := r.processTemplateRequest(template, request)
|
||||
if httpResults {
|
||||
results = httpResults
|
||||
for _, request := range template.RequestsHTTP {
|
||||
httpResults := r.processTemplateRequest(template, request)
|
||||
if httpResults {
|
||||
results = httpResults
|
||||
}
|
||||
}
|
||||
case *workflows.Workflow:
|
||||
workflow := t.(*workflows.Workflow)
|
||||
r.ProcessWorkflowWithList(workflow)
|
||||
default:
|
||||
gologger.Errorf("Could not parse file '%s'\n", r.options.Templates)
|
||||
}
|
||||
}
|
||||
if !results {
|
||||
|
@ -385,3 +388,19 @@ func (r *Runner) ProcessWorkflow(workflow *workflows.Workflow, URL string) error
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runner) parse(file string) interface{} {
|
||||
// check if it's a template
|
||||
template, errTemplate := templates.ParseTemplate(r.options.Templates)
|
||||
if errTemplate == nil {
|
||||
return template
|
||||
}
|
||||
|
||||
// check if it's a workflow
|
||||
workflow, errWorkflow := workflows.Parse(r.options.Templates)
|
||||
if errWorkflow == nil {
|
||||
return workflow
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,16 +14,13 @@ func (options *Options) validateOptions() error {
|
|||
return errors.New("both verbose and silent mode specified")
|
||||
}
|
||||
|
||||
// Workflow needs to bypass the classical input checks
|
||||
if options.WorkflowFile == "" {
|
||||
// Check if a list of templates was provided and it exists
|
||||
if options.Templates == "" && !options.UpdateTemplates {
|
||||
return errors.New("no template/templates provided")
|
||||
}
|
||||
// Check if a list of templates was provided and it exists
|
||||
if options.Templates == "" && !options.UpdateTemplates {
|
||||
return errors.New("no template/templates provided")
|
||||
}
|
||||
|
||||
if options.Targets == "" && !options.Stdin && !options.UpdateTemplates {
|
||||
return errors.New("no target input provided")
|
||||
}
|
||||
if options.Targets == "" && !options.Stdin && !options.UpdateTemplates {
|
||||
return errors.New("no target input provided")
|
||||
}
|
||||
|
||||
// Validate proxy options if provided
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
|
@ -20,10 +21,13 @@ func ParseTemplate(file string) (*Template, error) {
|
|||
|
||||
err = yaml.NewDecoder(f).Decode(template)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
f.Close()
|
||||
defer f.Close()
|
||||
|
||||
if len(template.RequestsHTTP)+len(template.RequestsDNS) <= 0 {
|
||||
return nil, errors.New("No requests defined")
|
||||
}
|
||||
|
||||
// Compile the matchers and the extractors for http requests
|
||||
for _, request := range template.RequestsHTTP {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package workflows
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
@ -21,5 +22,9 @@ func Parse(file string) (*Workflow, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if workflow.Logic == "" {
|
||||
return nil, errors.New("No logic provided")
|
||||
}
|
||||
|
||||
return workflow, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue