2021-07-05 04:35:53 +05:30
|
|
|
package templates
|
|
|
|
|
|
|
|
|
|
import (
|
2021-08-30 16:58:11 +05:30
|
|
|
"github.com/pkg/errors"
|
2021-11-25 17:09:20 +02:00
|
|
|
|
2021-07-05 21:56:40 +05:30
|
|
|
"github.com/projectdiscovery/gologger"
|
2023-10-17 17:44:13 +05:30
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/model"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/workflows"
|
2021-07-05 04:35:53 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// compileWorkflow compiles the workflow for execution
|
2023-05-31 16:58:10 -04:00
|
|
|
func compileWorkflow(path string, preprocessor Preprocessor, options *protocols.ExecutorOptions, workflow *workflows.Workflow, loader model.WorkflowLoader) {
|
2021-07-05 04:35:53 +05:30
|
|
|
for _, workflow := range workflow.Workflows {
|
2021-07-20 22:32:44 -07:00
|
|
|
if err := parseWorkflow(preprocessor, workflow, options, loader); err != nil {
|
2021-08-30 16:58:11 +05:30
|
|
|
gologger.Warning().Msgf("Could not parse workflow %s: %v\n", path, err)
|
2021-07-05 21:56:40 +05:30
|
|
|
continue
|
2021-07-05 04:35:53 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parseWorkflow parses and compiles all templates in a workflow recursively
|
2023-05-31 16:58:10 -04:00
|
|
|
func parseWorkflow(preprocessor Preprocessor, workflow *workflows.WorkflowTemplate, options *protocols.ExecutorOptions, loader model.WorkflowLoader) error {
|
2021-07-05 21:01:51 +05:30
|
|
|
shouldNotValidate := false
|
|
|
|
|
|
2022-06-11 14:41:43 +06:00
|
|
|
if workflow.Template == "" && workflow.Tags.IsEmpty() {
|
2021-08-30 16:58:11 +05:30
|
|
|
return errors.New("invalid workflow with no templates or tags")
|
|
|
|
|
}
|
2021-07-05 21:01:51 +05:30
|
|
|
if len(workflow.Subtemplates) > 0 || len(workflow.Matchers) > 0 {
|
|
|
|
|
shouldNotValidate = true
|
|
|
|
|
}
|
2021-07-20 22:32:44 -07:00
|
|
|
if err := parseWorkflowTemplate(workflow, preprocessor, options, loader, shouldNotValidate); err != nil {
|
2021-07-05 04:35:53 +05:30
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
for _, subtemplates := range workflow.Subtemplates {
|
2021-07-20 22:32:44 -07:00
|
|
|
if err := parseWorkflow(preprocessor, subtemplates, options, loader); err != nil {
|
2021-07-05 21:56:40 +05:30
|
|
|
gologger.Warning().Msgf("Could not parse workflow: %v\n", err)
|
|
|
|
|
continue
|
2021-07-05 04:35:53 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, matcher := range workflow.Matchers {
|
2022-09-19 16:49:30 +05:30
|
|
|
if len(matcher.Name.ToSlice()) > 0 {
|
|
|
|
|
if err := matcher.Compile(); err != nil {
|
|
|
|
|
return errors.Wrap(err, "could not compile workflow matcher")
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-07-05 04:35:53 +05:30
|
|
|
for _, subtemplates := range matcher.Subtemplates {
|
2021-07-20 22:32:44 -07:00
|
|
|
if err := parseWorkflow(preprocessor, subtemplates, options, loader); err != nil {
|
2021-07-05 21:56:40 +05:30
|
|
|
gologger.Warning().Msgf("Could not parse workflow: %v\n", err)
|
|
|
|
|
continue
|
2021-07-05 04:35:53 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parseWorkflowTemplate parses a workflow template creating an executer
|
2023-05-31 16:58:10 -04:00
|
|
|
func parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, preprocessor Preprocessor, options *protocols.ExecutorOptions, loader model.WorkflowLoader, noValidate bool) error {
|
2021-07-05 04:35:53 +05:30
|
|
|
var paths []string
|
|
|
|
|
|
2021-08-19 15:17:25 +03:00
|
|
|
subTemplateTags := workflow.Tags
|
|
|
|
|
if !subTemplateTags.IsEmpty() {
|
|
|
|
|
paths = loader.GetTemplatePathsByTags(subTemplateTags.ToSlice())
|
2021-07-05 04:35:53 +05:30
|
|
|
} else {
|
2021-08-19 15:17:25 +03:00
|
|
|
paths = loader.GetTemplatePaths([]string{workflow.Template}, noValidate)
|
2021-07-05 04:35:53 +05:30
|
|
|
}
|
|
|
|
|
if len(paths) == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2021-11-22 00:19:53 +01:00
|
|
|
|
|
|
|
|
var workflowTemplates []*Template
|
|
|
|
|
|
2021-07-05 04:35:53 +05:30
|
|
|
for _, path := range paths {
|
2021-10-27 16:50:36 +05:30
|
|
|
template, err := Parse(path, preprocessor, options.Copy())
|
2021-07-05 04:35:53 +05:30
|
|
|
if err != nil {
|
2021-07-05 21:56:40 +05:30
|
|
|
gologger.Warning().Msgf("Could not parse workflow template %s: %v\n", path, err)
|
|
|
|
|
continue
|
2021-07-05 04:35:53 +05:30
|
|
|
}
|
|
|
|
|
if template.Executer == nil {
|
2021-07-05 21:56:40 +05:30
|
|
|
gologger.Warning().Msgf("Could not parse workflow template %s: no executer found\n", path)
|
|
|
|
|
continue
|
2021-07-05 04:35:53 +05:30
|
|
|
}
|
2024-03-01 21:30:03 +05:30
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-22 00:19:53 +01:00
|
|
|
workflowTemplates = append(workflowTemplates, template)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
finalTemplates, _ := ClusterTemplates(workflowTemplates, options.Copy())
|
|
|
|
|
for _, template := range finalTemplates {
|
2021-07-05 04:35:53 +05:30
|
|
|
workflow.Executers = append(workflow.Executers, &workflows.ProtocolExecuterPair{
|
2022-10-20 17:23:00 +05:30
|
|
|
Executer: template.Executer,
|
|
|
|
|
Options: options,
|
|
|
|
|
TemplateType: template.Type(),
|
2021-07-05 04:35:53 +05:30
|
|
|
})
|
|
|
|
|
}
|
2021-11-22 00:19:53 +01:00
|
|
|
|
2021-07-05 04:35:53 +05:30
|
|
|
return nil
|
|
|
|
|
}
|