add variable support to dsl, remove dynamicValues from request struct

This commit is contained in:
Sajad Parra 2021-11-24 22:19:42 +05:30
parent 1851e37aef
commit 7e9272776d
7 changed files with 27 additions and 15 deletions

View File

@ -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

View File

@ -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.

View File

@ -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:

View File

@ -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 {

View File

@ -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 {

View File

@ -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:

View File

@ -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)