-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
Copy pathworkflows.go
129 lines (116 loc) · 4.28 KB
/
workflows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package templates
import (
"github.com/pkg/errors"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/keys"
"github.com/projectdiscovery/nuclei/v3/pkg/model"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/stats"
"github.com/projectdiscovery/nuclei/v3/pkg/workflows"
)
// compileWorkflow compiles the workflow for execution
func compileWorkflow(path string, preprocessor Preprocessor, options *protocols.ExecutorOptions, workflow *workflows.Workflow, loader model.WorkflowLoader) {
for _, workflow := range workflow.Workflows {
if err := parseWorkflow(preprocessor, workflow, options, loader); err != nil {
gologger.Warning().Msgf("Could not parse workflow %s: %v\n", path, err)
continue
}
}
}
// parseWorkflow parses and compiles all templates in a workflow recursively
func parseWorkflow(preprocessor Preprocessor, workflow *workflows.WorkflowTemplate, options *protocols.ExecutorOptions, loader model.WorkflowLoader) error {
shouldNotValidate := false
if workflow.Template == "" && workflow.Tags.IsEmpty() {
return errors.New("invalid workflow with no templates or tags")
}
if len(workflow.Subtemplates) > 0 || len(workflow.Matchers) > 0 {
shouldNotValidate = true
}
if err := parseWorkflowTemplate(workflow, preprocessor, options, loader, shouldNotValidate); err != nil {
return err
}
for _, subtemplates := range workflow.Subtemplates {
if err := parseWorkflow(preprocessor, subtemplates, options, loader); err != nil {
gologger.Warning().Msgf("Could not parse workflow: %v\n", err)
continue
}
}
for _, matcher := range workflow.Matchers {
if len(matcher.Name.ToSlice()) > 0 {
if err := matcher.Compile(); err != nil {
return errors.Wrap(err, "could not compile workflow matcher")
}
}
for _, subtemplates := range matcher.Subtemplates {
if err := parseWorkflow(preprocessor, subtemplates, options, loader); err != nil {
gologger.Warning().Msgf("Could not parse workflow: %v\n", err)
continue
}
}
}
return nil
}
// parseWorkflowTemplate parses a workflow template creating an executer
func parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, preprocessor Preprocessor, options *protocols.ExecutorOptions, loader model.WorkflowLoader, noValidate bool) error {
var paths []string
subTemplateTags := workflow.Tags
if !subTemplateTags.IsEmpty() {
paths = loader.GetTemplatePathsByTags(subTemplateTags.ToSlice())
} else {
paths = loader.GetTemplatePaths([]string{workflow.Template}, noValidate)
}
if len(paths) == 0 {
return nil
}
var workflowTemplates []*Template
for _, path := range paths {
template, err := Parse(path, preprocessor, options.Copy())
if err != nil {
gologger.Warning().Msgf("Could not parse workflow template %s: %v\n", path, err)
continue
}
if template.Executer == nil {
gologger.Warning().Msgf("Could not parse workflow template %s: no executer found\n", path)
continue
}
if options.Options.DisableUnsignedTemplates && !template.Verified {
// skip unverified templates when prompted to do so
stats.Increment(SkippedUnsignedStats)
continue
}
if template.UsesRequestSignature() && !template.Verified {
stats.Increment(SkippedRequestSignatureStats)
continue
}
if len(template.RequestsCode) > 0 {
if !options.Options.EnableCodeTemplates {
gologger.Warning().Msgf("`-code` flag not found, skipping code template from workflow: %v\n", path)
continue
} else if !template.Verified {
// unverfied code templates are not allowed in workflows
gologger.Warning().Msgf("skipping unverified code template from workflow: %v\n", path)
continue
}
}
// increment signed/unsigned counters
if template.Verified {
if template.TemplateVerifier == "" {
SignatureStats[keys.PDVerifier].Add(1)
} else {
SignatureStats[template.TemplateVerifier].Add(1)
}
} else {
SignatureStats[Unsigned].Add(1)
}
workflowTemplates = append(workflowTemplates, template)
}
finalTemplates, _ := ClusterTemplates(workflowTemplates, options.Copy())
for _, template := range finalTemplates {
workflow.Executers = append(workflow.Executers, &workflows.ProtocolExecuterPair{
Executer: template.Executer,
Options: options,
TemplateType: template.Type(),
})
}
return nil
}