fix multiple panics & missing matcher-status in flow templates (#4978)

* validate and fix empty internal-event

* fix on error with interactsh req

* disable clustering in flow & multiproto

* fix empty/missing matcher-status result

* fix cluster unit test

* fix no results found unit test
This commit is contained in:
Tarun Koyalwar
2024-04-03 17:19:06 +05:30
committed by GitHub
parent abc8ac8ee1
commit 3907e20bde
4 changed files with 83 additions and 21 deletions

View File

@@ -92,7 +92,11 @@ func (e *TemplateExecuter) Requests() int {
// Execute executes the protocol group and returns true or false if results were found.
func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
results := &atomic.Bool{}
// executed contains status of execution if it was successfully executed or not
// doesn't matter if it was matched or not
executed := &atomic.Bool{}
// matched in this case means something was exported / written to output
matched := &atomic.Bool{}
defer func() {
// it is essential to remove template context of `Scan i.e template x input pair`
// since it is of no use after scan is completed (regardless of success or failure)
@@ -101,11 +105,11 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
var lastMatcherEvent *output.InternalWrappedEvent
writeFailureCallback := func(event *output.InternalWrappedEvent, matcherStatus bool) {
if !results.Load() && matcherStatus {
if !matched.Load() && matcherStatus {
if err := e.options.Output.WriteFailure(event); err != nil {
gologger.Warning().Msgf("Could not write failure event to output: %s\n", err)
}
results.CompareAndSwap(false, true)
executed.CompareAndSwap(false, true)
}
}
@@ -133,11 +137,11 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
// If no results were found, and also interactsh is not being used
// in that case we can skip it, otherwise we've to show failure in
// case of matcher-status flag.
if !event.HasOperatorResult() && !event.UsesInteractsh {
if !event.HasOperatorResult() && event.InternalEvent != nil {
lastMatcherEvent = event
} else {
if writer.WriteResult(event, e.options.Output, e.options.Progress, e.options.IssuesClient) {
results.CompareAndSwap(false, true)
matched.Store(true)
} else {
lastMatcherEvent = event
}
@@ -152,7 +156,7 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
// so in compile step earlier we compile it to validate javascript syntax and other things
// and while executing we create new instance of flow executor everytime
if e.options.Flow != "" {
flowexec, err := flow.NewFlowExecutor(e.requests, ctx, e.options, results, e.program)
flowexec, err := flow.NewFlowExecutor(e.requests, ctx, e.options, executed, e.program)
if err != nil {
ctx.LogError(err)
return false, fmt.Errorf("could not create flow executor: %s", err)
@@ -169,7 +173,7 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
if lastMatcherEvent != nil {
writeFailureCallback(lastMatcherEvent, e.options.Options.MatcherStatus)
}
return results.Load(), errx
return executed.Load() || matched.Load(), errx
}
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.