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