diff --git a/v2/pkg/operators/matchers/match.go b/v2/pkg/operators/matchers/match.go index 84601be6e..d04a6149b 100644 --- a/v2/pkg/operators/matchers/match.go +++ b/v2/pkg/operators/matchers/match.go @@ -3,6 +3,9 @@ package matchers import ( "strings" + "github.com/Knetic/govaluate" + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/nuclei/v2/pkg/operators/common/dsl" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/expressions" ) @@ -39,7 +42,7 @@ func (m *Matcher) MatchSize(length int) bool { } // MatchWords matches a word check against a corpus. -func (m *Matcher) MatchWords(corpus string, dynamicValues map[string]interface{}) (bool, []string) { +func (m *Matcher) MatchWords(corpus string, data map[string]interface{}) (bool, []string) { if m.CaseInsensitive { corpus = strings.ToLower(corpus) } @@ -47,12 +50,12 @@ func (m *Matcher) MatchWords(corpus string, dynamicValues map[string]interface{} var matchedWords []string // Iterate over all the words accepted as valid for i, word := range m.Words { - if dynamicValues == nil { - dynamicValues = make(map[string]interface{}) + if data == nil { + data = make(map[string]interface{}) } var err error - word, err = expressions.Evaluate(word, dynamicValues) + word, err = expressions.Evaluate(word, data) if err != nil { continue } @@ -148,6 +151,18 @@ func (m *Matcher) MatchBinary(corpus string) (bool, []string) { func (m *Matcher) MatchDSL(data map[string]interface{}) bool { // Iterate over all the expressions accepted as valid for i, expression := range m.dslCompiled { + if varErr := expressions.ContainsUnresolvedVariables(expression.String()); varErr != nil { + resolvedExpression, err := expressions.Evaluate(expression.String(), data) + if err != nil { + gologger.Warning().Msgf("Could not evaluate expression: %s, error: %s", m.Name, err.Error()) + return false + } + expression, err = govaluate.NewEvaluableExpressionWithFunctions(resolvedExpression, dsl.HelperFunctions()) + if err != nil { + gologger.Warning().Msgf("Could not evaluate expression: %s, error: %s", m.Name, err.Error()) + return false + } + } result, err := expression.Evaluate(data) if err != nil { continue diff --git a/v2/pkg/protocols/http/http.go b/v2/pkg/protocols/http/http.go index 17a87588d..49e7c74de 100644 --- a/v2/pkg/protocols/http/http.go +++ b/v2/pkg/protocols/http/http.go @@ -134,7 +134,6 @@ type Request struct { generator *generators.PayloadGenerator // optional, only enabled when using payloads httpClient *retryablehttp.Client rawhttpClient *rawhttp.Client - dynamicValues map[string]interface{} // description: | // SelfContained specifies if the request is self contained. diff --git a/v2/pkg/protocols/http/operators.go b/v2/pkg/protocols/http/operators.go index 1f319ccff..70fd4d4c7 100644 --- a/v2/pkg/protocols/http/operators.go +++ b/v2/pkg/protocols/http/operators.go @@ -32,7 +32,7 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat case matchers.SizeMatcher: return matcher.Result(matcher.MatchSize(len(item))), []string{} case matchers.WordsMatcher: - return matcher.ResultWithMatchedSnippet(matcher.MatchWords(item, request.dynamicValues)) + return matcher.ResultWithMatchedSnippet(matcher.MatchWords(item, data)) case matchers.RegexMatcher: return matcher.ResultWithMatchedSnippet(matcher.MatchRegex(item)) case matchers.BinaryMatcher: diff --git a/v2/pkg/protocols/http/request.go b/v2/pkg/protocols/http/request.go index 8f2040782..405e45bf4 100644 --- a/v2/pkg/protocols/http/request.go +++ b/v2/pkg/protocols/http/request.go @@ -231,7 +231,7 @@ func (request *Request) ExecuteWithResults(reqURL string, dynamicValues, previou if reqURL == "" { reqURL = generatedHttpRequest.URL() } - request.dynamicValues = generatedHttpRequest.dynamicValues + // Check if hosts just keep erroring if request.options.HostErrorsCache != nil && request.options.HostErrorsCache.Check(reqURL) { break @@ -470,7 +470,7 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate } } - event := eventcreator.CreateEventWithAdditionalOptions(request, finalEvent, request.options.Options.Debug || request.options.Options.DebugResponse, func(internalWrappedEvent *output.InternalWrappedEvent) { + event := eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(generatedRequest.dynamicValues, finalEvent), request.options.Options.Debug || request.options.Options.DebugResponse, func(internalWrappedEvent *output.InternalWrappedEvent) { internalWrappedEvent.OperatorsResult.PayloadValues = generatedRequest.meta }) if hasInteractMarkers { diff --git a/v2/pkg/protocols/network/network.go b/v2/pkg/protocols/network/network.go index 09dcfb451..385b5bb7c 100644 --- a/v2/pkg/protocols/network/network.go +++ b/v2/pkg/protocols/network/network.go @@ -77,9 +77,8 @@ type Request struct { generator *generators.PayloadGenerator // cache any variables that may be needed for operation. - dialer *fastdialer.Dialer - options *protocols.ExecuterOptions - dynamicValues map[string]interface{} + dialer *fastdialer.Dialer + options *protocols.ExecuterOptions } type addressKV struct { diff --git a/v2/pkg/protocols/network/operators.go b/v2/pkg/protocols/network/operators.go index 010b11d61..d3083301b 100644 --- a/v2/pkg/protocols/network/operators.go +++ b/v2/pkg/protocols/network/operators.go @@ -23,7 +23,7 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat case matchers.SizeMatcher: return matcher.Result(matcher.MatchSize(len(itemStr))), []string{} case matchers.WordsMatcher: - return matcher.ResultWithMatchedSnippet(matcher.MatchWords(itemStr, request.dynamicValues)) + return matcher.ResultWithMatchedSnippet(matcher.MatchWords(itemStr, data)) case matchers.RegexMatcher: return matcher.ResultWithMatchedSnippet(matcher.MatchRegex(itemStr)) case matchers.BinaryMatcher: diff --git a/v2/pkg/protocols/network/request.go b/v2/pkg/protocols/network/request.go index 35da81d15..484f95ae2 100644 --- a/v2/pkg/protocols/network/request.go +++ b/v2/pkg/protocols/network/request.go @@ -78,6 +78,7 @@ func (request *Request) executeAddress(actualAddress, address, input string, sho } payloads := generators.BuildPayloadFromOptions(request.options.Options) + generators.MergeMaps(payloads, map[string]interface{}{"Hostname": address}) if request.generator != nil { iterator := request.generator.NewIterator() @@ -108,8 +109,6 @@ func (request *Request) executeRequestWithPayloads(actualAddress, address, input err error ) - request.dynamicValues = generators.MergeMaps(payloads, map[string]interface{}{"Hostname": address}) - if host, _, splitErr := net.SplitHostPort(actualAddress); splitErr == nil { hostname = host } @@ -267,7 +266,7 @@ func (request *Request) executeRequestWithPayloads(actualAddress, address, input var event *output.InternalWrappedEvent if len(interactshURLs) == 0 { - event = eventcreator.CreateEventWithAdditionalOptions(request, outputEvent, request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) { + event = eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(payloads, outputEvent), request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) { wrappedEvent.OperatorsResult.PayloadValues = payloads }) callback(event)