mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 23:25:27 +00:00
* use parsed options while signing * update project layout to v3 * fix .gitignore * remove example template * misc updates * bump tlsx version * hide template sig warning with env * js: retain value while using log * fix nil pointer derefernce * misc doc update --------- Co-authored-by: sandeep <8293321+ehsandeep@users.noreply.github.com>
125 lines
4.6 KiB
Go
125 lines
4.6 KiB
Go
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
|
|
}
|