From 5a690ca6169521b124920aca9eabaabd97b7616d Mon Sep 17 00:00:00 2001 From: Ice3man543 Date: Fri, 25 Dec 2020 20:39:09 +0530 Subject: [PATCH] More improvements, adding metadata for state between requests --- v2/pkg/protocols/dns/executer.go | 23 +++++++----- v2/pkg/protocols/dns/operators.go | 58 +++++++++++++++---------------- v2/pkg/protocols/dns/request.go | 5 ++- v2/pkg/protocols/protocols.go | 6 ++-- 4 files changed, 50 insertions(+), 42 deletions(-) diff --git a/v2/pkg/protocols/dns/executer.go b/v2/pkg/protocols/dns/executer.go index 15d819c8..a51d1a9d 100644 --- a/v2/pkg/protocols/dns/executer.go +++ b/v2/pkg/protocols/dns/executer.go @@ -11,6 +11,8 @@ type Executer struct { options *protocols.ExecuterOptions } +var _ protocols.Executer = &Executer{} + // NewExecuter creates a new request executer for list of requests func NewExecuter(requests []*Request, options *protocols.ExecuterOptions) *Executer { return &Executer{requests: requests, options: options} @@ -40,18 +42,20 @@ func (e *Executer) Execute(input string) (bool, error) { var results bool for _, req := range e.requests { - events, err := req.ExecuteWithResults(input) + events, err := req.ExecuteWithResults(input, nil) if err != nil { return false, err } // If we have a result field, we should add a result to slice. for _, event := range events { - if event.OperatorsResult != nil { - for _, result := range req.makeResultEvent(event) { - results = true - e.options.Output.Write(result) - } + if event.OperatorsResult == nil { + continue + } + + for _, result := range req.makeResultEvent(event) { + results = true + e.options.Output.Write(result) } } } @@ -63,14 +67,15 @@ func (e *Executer) ExecuteWithResults(input string) ([]*output.ResultEvent, erro var results []*output.ResultEvent for _, req := range e.requests { - events, err := req.ExecuteWithResults(input) + events, err := req.ExecuteWithResults(input, nil) if err != nil { return nil, err } for _, event := range events { - if event.OperatorsResult != nil { - results = append(results, req.makeResultEvent(event)...) + if event.OperatorsResult == nil { + continue } + results = append(results, req.makeResultEvent(event)...) } } return results, nil diff --git a/v2/pkg/protocols/dns/operators.go b/v2/pkg/protocols/dns/operators.go index c0e91e59..af044aeb 100644 --- a/v2/pkg/protocols/dns/operators.go +++ b/v2/pkg/protocols/dns/operators.go @@ -78,35 +78,6 @@ func (r *Request) Extract(data map[string]interface{}, extractor *extractors.Ext return nil } -// makeResultEvent creates a result event from internal wrapped event -func (r *Request) makeResultEvent(wrapped *output.InternalWrappedEvent) []*output.ResultEvent { - results := make([]*output.ResultEvent, len(wrapped.OperatorsResult.Matches)+1) - - data := output.ResultEvent{ - TemplateID: r.options.TemplateID, - Info: r.options.TemplateInfo, - Type: "dns", - Host: wrapped.InternalEvent["host"].(string), - Matched: wrapped.InternalEvent["matched"].(string), - ExtractedResults: wrapped.OperatorsResult.OutputExtracts, - } - if r.options.Options.JSONRequests { - data.Request = wrapped.InternalEvent["request"].(string) - data.Response = wrapped.InternalEvent["raw"].(string) - } - - // If we have multiple matchers with names, write each of them separately. - if len(wrapped.OperatorsResult.Matches) > 0 { - for k := range wrapped.OperatorsResult.Matches { - data.MatcherName = k - results = append(results, &data) - } - } else { - results = append(results, &data) - } - return results -} - // responseToDSLMap converts a DNS response to a map for use in DSL matching func responseToDSLMap(req, resp *dns.Msg, host, matched string) output.InternalEvent { data := make(output.InternalEvent, 8) @@ -146,3 +117,32 @@ func responseToDSLMap(req, resp *dns.Msg, host, matched string) output.InternalE data["raw"] = rawData return data } + +// makeResultEvent creates a result event from internal wrapped event +func (r *Request) makeResultEvent(wrapped *output.InternalWrappedEvent) []*output.ResultEvent { + results := make([]*output.ResultEvent, len(wrapped.OperatorsResult.Matches)+1) + + data := output.ResultEvent{ + TemplateID: r.options.TemplateID, + Info: r.options.TemplateInfo, + Type: "dns", + Host: wrapped.InternalEvent["host"].(string), + Matched: wrapped.InternalEvent["matched"].(string), + ExtractedResults: wrapped.OperatorsResult.OutputExtracts, + } + if r.options.Options.JSONRequests { + data.Request = wrapped.InternalEvent["request"].(string) + data.Response = wrapped.InternalEvent["raw"].(string) + } + + // If we have multiple matchers with names, write each of them separately. + if len(wrapped.OperatorsResult.Matches) > 0 { + for k := range wrapped.OperatorsResult.Matches { + data.MatcherName = k + results = append(results, &data) + } + } else { + results = append(results, &data) + } + return results +} diff --git a/v2/pkg/protocols/dns/request.go b/v2/pkg/protocols/dns/request.go index ecbbdb20..d12e2d45 100644 --- a/v2/pkg/protocols/dns/request.go +++ b/v2/pkg/protocols/dns/request.go @@ -8,10 +8,13 @@ import ( "github.com/pkg/errors" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v2/pkg/output" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols" ) +var _ protocols.Request = &Request{} + // ExecuteWithResults executes the protocol requests and returns results instead of writing them. -func (r *Request) ExecuteWithResults(input string) ([]*output.InternalWrappedEvent, error) { +func (r *Request) ExecuteWithResults(input string, metadata output.InternalEvent) ([]*output.InternalWrappedEvent, error) { // Parse the URL and return domain if URL. var domain string if isURL(input) { diff --git a/v2/pkg/protocols/protocols.go b/v2/pkg/protocols/protocols.go index 1469b296..138109ec 100644 --- a/v2/pkg/protocols/protocols.go +++ b/v2/pkg/protocols/protocols.go @@ -12,7 +12,7 @@ import ( // Executer is an interface implemented any protocol based request executer. type Executer interface { // Compile compiles the execution generators preparing any requests possible. - Compile(options ExecuterOptions) error + Compile() error // Requests returns the total number of requests the rule will perform Requests() int64 // Execute executes the protocol group and returns true or false if results were found. @@ -40,7 +40,7 @@ type ExecuterOptions struct { // Request is an interface implemented any protocol based request generator. type Request interface { // Compile compiles the request generators preparing any requests possible. - Compile(options ExecuterOptions) error + Compile(options *ExecuterOptions) error // Requests returns the total number of requests the rule will perform Requests() int64 // Match performs matching operation for a matcher on model and returns true or false. @@ -48,5 +48,5 @@ type Request interface { // Extract performs extracting operation for a extractor on model and returns true or false. Extract(data map[string]interface{}, matcher *extractors.Extractor) map[string]struct{} // ExecuteWithResults executes the protocol requests and returns results instead of writing them. - ExecuteWithResults(input string) ([]*output.InternalWrappedEvent, error) + ExecuteWithResults(input string, metadata output.InternalEvent) ([]*output.InternalWrappedEvent, error) }