mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 04:25:31 +00:00
error handling + support offlinehttp in flow templates (#4653)
This commit is contained in:
parent
44745cb0c9
commit
68b9dd52ad
@ -183,8 +183,9 @@ func (template *Template) compileProtocolRequests(options *protocols.ExecutorOpt
|
||||
requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsJavascript)...)
|
||||
}
|
||||
}
|
||||
template.Executer = tmplexec.NewTemplateExecuter(requests, options)
|
||||
return nil
|
||||
var err error
|
||||
template.Executer, err = tmplexec.NewTemplateExecuter(requests, options)
|
||||
return err
|
||||
}
|
||||
|
||||
// convertRequestToProtocolsRequest is a convenience wrapper to convert
|
||||
@ -228,8 +229,13 @@ mainLoop:
|
||||
}
|
||||
if len(operatorsList) > 0 {
|
||||
options.Operators = operatorsList
|
||||
template.Executer = tmplexec.NewTemplateExecuter([]protocols.Request{&offlinehttp.Request{}}, options)
|
||||
return nil
|
||||
var err error
|
||||
template.Executer, err = tmplexec.NewTemplateExecuter([]protocols.Request{&offlinehttp.Request{}}, options)
|
||||
if err != nil {
|
||||
// it seems like flow executor cannot be used for offline http matching (ex:http(1) && http(2))
|
||||
return ErrIncompatibleWithOfflineMatching
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return ErrIncompatibleWithOfflineMatching
|
||||
|
||||
@ -31,7 +31,7 @@ type TemplateExecuter struct {
|
||||
var _ protocols.Executer = &TemplateExecuter{}
|
||||
|
||||
// NewTemplateExecuter creates a new request TemplateExecuter for list of requests
|
||||
func NewTemplateExecuter(requests []protocols.Request, options *protocols.ExecutorOptions) *TemplateExecuter {
|
||||
func NewTemplateExecuter(requests []protocols.Request, options *protocols.ExecutorOptions) (*TemplateExecuter, error) {
|
||||
isMultiProto := false
|
||||
lastProto := ""
|
||||
for _, request := range requests {
|
||||
@ -47,7 +47,11 @@ func NewTemplateExecuter(requests []protocols.Request, options *protocols.Execut
|
||||
// we use a dummy input here because goal of flow executor at this point is to just check
|
||||
// syntax and other things are correct before proceeding to actual execution
|
||||
// during execution new instance of flow will be created as it is tightly coupled with lot of executor options
|
||||
e.engine = flow.NewFlowExecutor(requests, scan.NewScanContext(contextargs.NewWithInput("dummy")), options, e.results)
|
||||
var err error
|
||||
e.engine, err = flow.NewFlowExecutor(requests, scan.NewScanContext(contextargs.NewWithInput("dummy")), options, e.results)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create flow executor: %s", err)
|
||||
}
|
||||
} else {
|
||||
// Review:
|
||||
// multiproto engine is only used if there is more than one protocol in template
|
||||
@ -58,8 +62,7 @@ func NewTemplateExecuter(requests []protocols.Request, options *protocols.Execut
|
||||
e.engine = generic.NewGenericEngine(requests, options, e.results)
|
||||
}
|
||||
}
|
||||
|
||||
return e
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// Compile compiles the execution generators preparing any requests possible.
|
||||
@ -146,7 +149,7 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
var err error
|
||||
var errx error
|
||||
|
||||
// Note: this is required for flow executor
|
||||
// flow executer is tightly coupled with lot of executor options
|
||||
@ -155,20 +158,24 @@ 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 := flow.NewFlowExecutor(e.requests, ctx, e.options, results)
|
||||
flowexec, err := flow.NewFlowExecutor(e.requests, ctx, e.options, results)
|
||||
if err != nil {
|
||||
ctx.LogError(err)
|
||||
return false, fmt.Errorf("could not create flow executor: %s", err)
|
||||
}
|
||||
if err := flowexec.Compile(); err != nil {
|
||||
ctx.LogError(err)
|
||||
return false, err
|
||||
}
|
||||
err = flowexec.ExecuteWithResults(ctx)
|
||||
errx = flowexec.ExecuteWithResults(ctx)
|
||||
} else {
|
||||
err = e.engine.ExecuteWithResults(ctx)
|
||||
errx = e.engine.ExecuteWithResults(ctx)
|
||||
}
|
||||
|
||||
if lastMatcherEvent != nil {
|
||||
writeFailureCallback(lastMatcherEvent, e.options.Options.MatcherStatus)
|
||||
}
|
||||
return results.Load(), err
|
||||
return results.Load(), errx
|
||||
}
|
||||
|
||||
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
|
||||
|
||||
@ -55,7 +55,7 @@ type FlowExecutor struct {
|
||||
// NewFlowExecutor creates a new flow executor from a list of requests
|
||||
// Note: Unlike other engine for every target x template flow needs to be compiled and executed everytime
|
||||
// unlike other engines where we compile once and execute multiple times
|
||||
func NewFlowExecutor(requests []protocols.Request, ctx *scan.ScanContext, options *protocols.ExecutorOptions, results *atomic.Bool) *FlowExecutor {
|
||||
func NewFlowExecutor(requests []protocols.Request, ctx *scan.ScanContext, options *protocols.ExecutorOptions, results *atomic.Bool) (*FlowExecutor, error) {
|
||||
allprotos := make(map[string][]protocols.Request)
|
||||
for _, req := range requests {
|
||||
switch req.Type() {
|
||||
@ -79,9 +79,11 @@ func NewFlowExecutor(requests []protocols.Request, ctx *scan.ScanContext, option
|
||||
allprotos[templateTypes.CodeProtocol.String()] = append(allprotos[templateTypes.CodeProtocol.String()], req)
|
||||
case templateTypes.JavascriptProtocol:
|
||||
allprotos[templateTypes.JavascriptProtocol.String()] = append(allprotos[templateTypes.JavascriptProtocol.String()], req)
|
||||
case templateTypes.OfflineHTTPProtocol:
|
||||
// offlinehttp is run in passive mode but templates are same so instead of using offlinehttp() we use http() in flow
|
||||
allprotos[templateTypes.HTTPProtocol.String()] = append(allprotos[templateTypes.OfflineHTTPProtocol.String()], req)
|
||||
default:
|
||||
ctx.LogError(fmt.Errorf("invalid request type %s", req.Type().String()))
|
||||
return nil
|
||||
return nil, fmt.Errorf("invalid request type %s", req.Type().String())
|
||||
}
|
||||
}
|
||||
f := &FlowExecutor{
|
||||
@ -96,7 +98,7 @@ func NewFlowExecutor(requests []protocols.Request, ctx *scan.ScanContext, option
|
||||
jsVM: protocolstate.NewJSRuntime(),
|
||||
ctx: ctx,
|
||||
}
|
||||
return f
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Compile compiles js program and registers all functions
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user