diff --git a/cmd/integration-test/workflow.go b/cmd/integration-test/workflow.go index 3ffd28871..8672283b6 100644 --- a/cmd/integration-test/workflow.go +++ b/cmd/integration-test/workflow.go @@ -5,6 +5,7 @@ import ( "io" "net/http" "net/http/httptest" + "strings" "github.com/julienschmidt/httprouter" @@ -16,6 +17,7 @@ var workflowTestcases = []TestCaseInfo{ {Path: "workflow/condition-matched.yaml", TestCase: &workflowConditionMatched{}}, {Path: "workflow/condition-unmatched.yaml", TestCase: &workflowConditionUnmatch{}}, {Path: "workflow/matcher-name.yaml", TestCase: &workflowMatcherName{}}, + {Path: "workflow/complex-conditions.yaml", TestCase: &workflowComplexConditions{}}, {Path: "workflow/http-value-share-workflow.yaml", TestCase: &workflowHttpKeyValueShare{}}, {Path: "workflow/dns-value-share-workflow.yaml", TestCase: &workflowDnsKeyValueShare{}}, {Path: "workflow/shared-cookie.yaml", TestCase: &workflowSharedCookies{}}, @@ -97,6 +99,30 @@ func (h *workflowMatcherName) Execute(filePath string) error { return expectResultsCount(results, 1) } +type workflowComplexConditions struct{} + +// Execute executes a test case and returns an error if occurred +func (h *workflowComplexConditions) Execute(filePath string) error { + router := httprouter.New() + router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + fmt.Fprintf(w, "This is test matcher text") + }) + ts := httptest.NewServer(router) + defer ts.Close() + + results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug) + if err != nil { + return err + } + + for _, result := range results { + if !strings.Contains(result, "test-matcher-3") { + return fmt.Errorf("incorrect result: the \"basic-get-third:test-matcher-3\" and only that should be matched!\nResults:\n\t%s", strings.Join(results, "\n\t")) + } + } + return expectResultsCount(results, 2) +} + type workflowHttpKeyValueShare struct{} // Execute executes a test case and returns an error if occurred diff --git a/integration_tests/workflow/complex-conditions.yaml b/integration_tests/workflow/complex-conditions.yaml new file mode 100644 index 000000000..bd1e66be5 --- /dev/null +++ b/integration_tests/workflow/complex-conditions.yaml @@ -0,0 +1,23 @@ +id: complex-conditions-workflow + +info: + name: Complex Conditions Workflow + author: tovask + severity: info + description: Workflow to test a complex scenario, e.g. race conditions when evaluating the results of the templates + +workflows: + - template: workflow/match-1.yaml + subtemplates: + - template: workflow/nomatch-1.yaml + subtemplates: + - template: workflow/match-2.yaml + - template: workflow/match-3.yaml + - template: workflow/match-2.yaml + matchers: + - name: test-matcher + subtemplates: + - template: workflow/nomatch-1.yaml + subtemplates: + - template: workflow/match-1.yaml + - template: workflow/match-3.yaml diff --git a/integration_tests/workflow/match-3.yaml b/integration_tests/workflow/match-3.yaml new file mode 100644 index 000000000..b2e23fb99 --- /dev/null +++ b/integration_tests/workflow/match-3.yaml @@ -0,0 +1,16 @@ +id: basic-get-third + +info: + name: Basic 3rd GET Request + author: tovask + severity: info + +http: + - method: GET + path: + - "{{BaseURL}}" + matchers: + - type: word + name: test-matcher-3 + words: + - "This is test matcher text" diff --git a/pkg/core/workflow_execute.go b/pkg/core/workflow_execute.go index 19d6f0d69..c17a1af8d 100644 --- a/pkg/core/workflow_execute.go +++ b/pkg/core/workflow_execute.go @@ -138,7 +138,9 @@ func (e *Engine) runWorkflowStep(template *workflows.WorkflowTemplate, ctx *scan go func(subtemplate *workflows.WorkflowTemplate) { defer swg.Done() - if err := e.runWorkflowStep(subtemplate, ctx, results, swg, w); err != nil { + // create a new context with the same input but with unset callbacks + subCtx := scan.NewScanContext(ctx.Input) + if err := e.runWorkflowStep(subtemplate, subCtx, results, swg, w); err != nil { gologger.Warning().Msgf(workflowStepExecutionError, subtemplate.Template, err) } }(subtemplate) @@ -162,7 +164,9 @@ func (e *Engine) runWorkflowStep(template *workflows.WorkflowTemplate, ctx *scan swg.Add() go func(template *workflows.WorkflowTemplate) { - if err := e.runWorkflowStep(template, ctx, results, swg, w); err != nil { + // create a new context with the same input but with unset callbacks + subCtx := scan.NewScanContext(ctx.Input) + if err := e.runWorkflowStep(template, subCtx, results, swg, w); err != nil { gologger.Warning().Msgf(workflowStepExecutionError, template.Template, err) } swg.Done()