mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-24 02:25:25 +00:00
fix(multiproto): missing previous InternalEvents output when ExecuteWithResults (#5967)
Signed-off-by: Dwi Siswanto <git@dw1.io>
This commit is contained in:
parent
a7f7616db9
commit
2450ecb503
@ -2,6 +2,7 @@ package multiproto
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
@ -9,6 +10,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
)
|
||||
|
||||
@ -60,11 +62,46 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
|
||||
m.options.GetTemplateCtx(ctx.Input.MetaInput).Set(key, value)
|
||||
})
|
||||
|
||||
// callback to process results from all protocols
|
||||
multiProtoCallback := func(event *output.InternalWrappedEvent) {
|
||||
previous := mapsutil.NewSyncLockMap[string, any]()
|
||||
|
||||
// template context: contains values extracted using `internal` extractor from previous protocols
|
||||
// these values are extracted from each protocol in queue and are passed to next protocol in queue
|
||||
// instead of adding seperator field to handle such cases these values are appended to `dynamicValues` (which are meant to be used in workflows)
|
||||
// this makes it possible to use multi protocol templates in workflows
|
||||
// Note: internal extractor values take precedence over dynamicValues from workflows (i.e other templates in workflow)
|
||||
|
||||
// execute all protocols in the queue
|
||||
for _, req := range m.requests {
|
||||
select {
|
||||
case <-ctx.Context().Done():
|
||||
return ctx.Context().Err()
|
||||
default:
|
||||
}
|
||||
inputItem := ctx.Input.Clone()
|
||||
if m.options.InputHelper != nil && ctx.Input.MetaInput.Input != "" {
|
||||
if inputItem.MetaInput.Input = m.options.InputHelper.Transform(inputItem.MetaInput.Input, req.Type()); inputItem.MetaInput.Input == "" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// FIXME: this hack of using hash to get templateCtx has known issues scan context based approach should be adopted ASAP
|
||||
values := m.options.GetTemplateCtx(inputItem.MetaInput).GetAll()
|
||||
err := req.ExecuteWithResults(inputItem, output.InternalEvent(values), output.InternalEvent(previous.GetAll()), func(event *output.InternalWrappedEvent) {
|
||||
if event == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ID := req.GetID()
|
||||
if ID != "" {
|
||||
builder := &strings.Builder{}
|
||||
for k, v := range event.InternalEvent {
|
||||
builder.WriteString(ID)
|
||||
builder.WriteString("_")
|
||||
builder.WriteString(k)
|
||||
_ = previous.Set(builder.String(), v)
|
||||
builder.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
// log event and generate result for the event
|
||||
ctx.LogEvent(event)
|
||||
// export dynamic values from operators (i.e internal:true)
|
||||
@ -94,30 +131,7 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
|
||||
// evaluate all variables after execution of each protocol
|
||||
variableMap := m.options.Variables.Evaluate(m.options.GetTemplateCtx(ctx.Input.MetaInput).GetAll())
|
||||
m.options.GetTemplateCtx(ctx.Input.MetaInput).Merge(variableMap) // merge all variables into template context
|
||||
}
|
||||
|
||||
// template context: contains values extracted using `internal` extractor from previous protocols
|
||||
// these values are extracted from each protocol in queue and are passed to next protocol in queue
|
||||
// instead of adding seperator field to handle such cases these values are appended to `dynamicValues` (which are meant to be used in workflows)
|
||||
// this makes it possible to use multi protocol templates in workflows
|
||||
// Note: internal extractor values take precedence over dynamicValues from workflows (i.e other templates in workflow)
|
||||
|
||||
// execute all protocols in the queue
|
||||
for _, req := range m.requests {
|
||||
select {
|
||||
case <-ctx.Context().Done():
|
||||
return ctx.Context().Err()
|
||||
default:
|
||||
}
|
||||
inputItem := ctx.Input.Clone()
|
||||
if m.options.InputHelper != nil && ctx.Input.MetaInput.Input != "" {
|
||||
if inputItem.MetaInput.Input = m.options.InputHelper.Transform(inputItem.MetaInput.Input, req.Type()); inputItem.MetaInput.Input == "" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// FIXME: this hack of using hash to get templateCtx has known issues scan context based approach should be adopted ASAP
|
||||
values := m.options.GetTemplateCtx(inputItem.MetaInput).GetAll()
|
||||
err := req.ExecuteWithResults(inputItem, output.InternalEvent(values), nil, multiProtoCallback)
|
||||
})
|
||||
// in case of fatal error skip execution of next protocols
|
||||
if err != nil {
|
||||
// always log errors
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user