forked from projectdiscovery/nuclei
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathworkflows.go
124 lines (109 loc) · 4.61 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
package workflows
import (
"fmt"
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/stringslice"
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
)
// Workflow is a workflow to execute with chained requests, etc.
type Workflow struct {
// description: |
// Workflows is a list of workflows to execute for a template.
Workflows []*WorkflowTemplate `yaml:"workflows,omitempty" json:"workflows,omitempty" jsonschema:"title=list of workflows to execute,description=List of workflows to execute for template"`
Options *protocols.ExecutorOptions `yaml:"-" json:"-"`
}
// WorkflowTemplate is a template to be run as part of a workflow
type WorkflowTemplate struct {
// description: |
// Template is a single template or directory to execute as part of workflow.
// examples:
// - name: A single template
// value: "\"dns/worksites-detection.yaml\""
// - name: A template directory
// value: "\"misconfigurations/aem\""
Template string `yaml:"template,omitempty" json:"template,omitempty" jsonschema:"title=template/directory to execute,description=Template or directory to execute as part of workflow"`
// description: |
// Tags to run templates based on.
Tags stringslice.StringSlice `yaml:"tags,omitempty" json:"tags,omitempty" jsonschema:"title=tags to execute,description=Tags to run template based on"`
// description: |
// Matchers perform name based matching to run subtemplates for a workflow.
Matchers []*Matcher `yaml:"matchers,omitempty" json:"matchers,omitempty" jsonschema:"title=name based template result matchers,description=Matchers perform name based matching to run subtemplates for a workflow"`
// description: |
// Subtemplates are run if the `template` field Template matches.
Subtemplates []*WorkflowTemplate `yaml:"subtemplates,omitempty" json:"subtemplates,omitempty" jsonschema:"title=subtemplate based result matchers,description=Subtemplates are ran if the template field Template matches"`
// Executers perform the actual execution for the workflow template
Executers []*ProtocolExecuterPair `yaml:"-" json:"-"`
}
// ProtocolExecuterPair is a pair of protocol executer and its options
type ProtocolExecuterPair struct {
Executer protocols.Executer
Options *protocols.ExecutorOptions
TemplateType templateTypes.ProtocolType
}
// Matcher performs conditional matching on the workflow template results.
type Matcher struct {
// description: |
// Name is the name of the items to match.
Name stringslice.StringSlice `yaml:"name,omitempty" json:"name,omitempty" jsonschema:"title=name of items to match,description=Name of items to match"`
// description: |
// Condition is the optional condition between names. By default,
// the condition is assumed to be OR.
// values:
// - "and"
// - "or"
Condition string `yaml:"condition,omitempty" json:"condition,omitempty" jsonschema:"title=condition between names,description=Condition between the names,enum=and,enum=or"`
// description: |
// Subtemplates are run if the name of matcher matches.
Subtemplates []*WorkflowTemplate `yaml:"subtemplates,omitempty" json:"subtemplates,omitempty" jsonschema:"title=templates to run after match,description=Templates to run after match"`
condition ConditionType
}
// ConditionType is the type of condition for matcher
type ConditionType int
const (
// ANDCondition matches responses with AND condition in arguments.
ANDCondition ConditionType = iota + 1
// ORCondition matches responses with AND condition in arguments.
ORCondition
)
// ConditionTypes is a table for conversion of condition type from string.
var ConditionTypes = map[string]ConditionType{
"and": ANDCondition,
"or": ORCondition,
}
// Compile compiles the matcher for workflow
func (matcher *Matcher) Compile() error {
var ok bool
if matcher.Condition != "" {
matcher.condition, ok = ConditionTypes[matcher.Condition]
if !ok {
return fmt.Errorf("unknown condition specified: %s", matcher.Condition)
}
} else {
matcher.condition = ORCondition
}
return nil
}
// Match matches a name for matcher names or name
func (matcher *Matcher) Match(result *operators.Result) bool {
names := matcher.Name.ToSlice()
if len(names) == 0 {
return false
}
for i, name := range names {
matchOK := result.HasMatch(name)
extractOK := result.HasExtract(name)
if !matchOK && !extractOK {
if matcher.condition == ANDCondition {
return false
}
continue
}
if matcher.condition == ORCondition {
return true
} else if len(names)-1 == i {
return true
}
}
return false
}