105 lines
2.7 KiB
Go
Raw Normal View History

2020-04-04 00:16:27 +05:30
package matchers
import (
2021-02-24 11:23:22 +05:30
"encoding/hex"
2020-04-04 00:16:27 +05:30
"fmt"
"regexp"
"strings"
2020-04-26 23:32:58 +02:00
"github.com/Knetic/govaluate"
2021-09-07 17:31:46 +03:00
"github.com/projectdiscovery/nuclei/v2/pkg/operators/common/dsl"
2020-04-04 00:16:27 +05:30
)
// CompileMatchers performs the initial setup operation on a matcher
2021-11-25 16:57:43 +02:00
func (matcher *Matcher) CompileMatchers() error {
2020-04-04 00:16:27 +05:30
var ok bool
2021-02-24 11:23:22 +05:30
// Support hexadecimal encoding for matchers too.
2021-11-25 16:57:43 +02:00
if matcher.Encoding == "hex" {
for i, word := range matcher.Words {
2021-02-24 11:23:22 +05:30
if decoded, err := hex.DecodeString(word); err == nil && len(decoded) > 0 {
2021-11-25 16:57:43 +02:00
matcher.Words[i] = string(decoded)
2021-02-24 11:23:22 +05:30
}
}
}
2021-09-07 17:31:46 +03:00
// Set up the matcher type
2021-11-25 16:57:43 +02:00
computedType, err := toMatcherTypes(matcher.GetType().String())
if err != nil {
2021-11-25 16:57:43 +02:00
return fmt.Errorf("unknown matcher type specified: %s", matcher.Type)
2020-04-04 00:16:27 +05:30
}
2021-11-25 16:57:43 +02:00
matcher.matcherType = computedType
// Validate the matcher structure
if err := matcher.Validate(); err != nil {
return err
}
// By default, match on body if user hasn't provided any specific items
2021-11-25 16:57:43 +02:00
if matcher.Part == "" {
matcher.Part = "body"
}
2020-04-04 00:16:27 +05:30
// Compile the regexes
2021-11-25 16:57:43 +02:00
for _, regex := range matcher.Regex {
2020-04-04 00:16:27 +05:30
compiled, err := regexp.Compile(regex)
if err != nil {
return fmt.Errorf("could not compile regex: %s", regex)
}
2021-11-25 16:57:43 +02:00
matcher.regexCompiled = append(matcher.regexCompiled, compiled)
2020-04-04 00:16:27 +05:30
}
// Compile and validate binary Values in matcher
2021-11-25 16:57:43 +02:00
for _, value := range matcher.Binary {
if decoded, err := hex.DecodeString(value); err != nil {
return fmt.Errorf("could not hex decode binary: %s", value)
} else {
2021-11-25 16:57:43 +02:00
matcher.binaryDecoded = append(matcher.binaryDecoded, string(decoded))
}
}
2020-04-26 23:32:58 +02:00
// Compile the dsl expressions
2021-12-07 18:17:34 +02:00
for _, dslExpression := range matcher.DSL {
compiledExpression, err := govaluate.NewEvaluableExpressionWithFunctions(dslExpression, dsl.HelperFunctions())
2020-04-26 23:32:58 +02:00
if err != nil {
return &DslCompilationError{DslSignature: dslExpression, WrappedError: err}
2020-04-26 23:32:58 +02:00
}
2021-12-07 18:17:34 +02:00
matcher.dslCompiled = append(matcher.dslCompiled, compiledExpression)
2020-04-26 23:32:58 +02:00
}
2021-09-07 17:31:46 +03:00
// Set up the condition type, if any.
2021-11-25 16:57:43 +02:00
if matcher.Condition != "" {
matcher.condition, ok = ConditionTypes[matcher.Condition]
2020-04-04 00:16:27 +05:30
if !ok {
2021-11-25 16:57:43 +02:00
return fmt.Errorf("unknown condition specified: %s", matcher.Condition)
2020-04-04 00:16:27 +05:30
}
} else {
2021-11-25 16:57:43 +02:00
matcher.condition = ORCondition
2020-04-04 00:16:27 +05:30
}
2021-11-25 16:57:43 +02:00
if matcher.CaseInsensitive {
if matcher.GetType() != WordsMatcher {
return fmt.Errorf("case-insensitive flag is supported only for 'word' matchers (not '%s')", matcher.Type)
}
2021-11-25 16:57:43 +02:00
for i := range matcher.Words {
matcher.Words[i] = strings.ToLower(matcher.Words[i])
}
}
2020-04-04 00:16:27 +05:30
return nil
}
type DslCompilationError struct {
DslSignature string
WrappedError error
}
func (e *DslCompilationError) Error() string {
return fmt.Sprintf("could not compile DSL expression: %s. %v", e.DslSignature, e.WrappedError)
}
func (e *DslCompilationError) Unwrap() error {
return e.WrappedError
}