mirror of https://github.com/daffainfo/nuclei.git
Work on operators package and generic protocol agnostic matching capabilities
parent
ff4c61a0eb
commit
8a64578890
|
@ -17,6 +17,10 @@ func (m *Matcher) CompileMatchers() error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("unknown matcher type specified: %s", m.Type)
|
return fmt.Errorf("unknown matcher type specified: %s", m.Type)
|
||||||
}
|
}
|
||||||
|
// By default, match on all if user hasn't provided any specific items
|
||||||
|
if m.Part == "" {
|
||||||
|
m.Part = "all"
|
||||||
|
}
|
||||||
|
|
||||||
// Compile the regexes
|
// Compile the regexes
|
||||||
for _, regex := range m.Regex {
|
for _, regex := range m.Regex {
|
||||||
|
|
|
@ -2,75 +2,34 @@ package matchers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net/http"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Match matches a http response again a given matcher
|
// Match matches a generic data response again a given matcher
|
||||||
func (m *Matcher) Match(resp *http.Response, body, headers string, duration time.Duration) bool {
|
func (m *Matcher) Match(data map[string]interface{}) bool {
|
||||||
switch m.matcherType {
|
part, ok := data[m.Part]
|
||||||
case StatusMatcher:
|
if !ok {
|
||||||
return m.isNegative(m.matchStatusCode(resp.StatusCode))
|
|
||||||
case SizeMatcher:
|
|
||||||
return m.isNegative(m.matchSizeCode(len(body)))
|
|
||||||
case WordsMatcher:
|
|
||||||
// Match the parts as required for word check
|
|
||||||
if m.Part == "body" {
|
|
||||||
return m.isNegative(m.matchWords(body))
|
|
||||||
} else if m.Part == "header" {
|
|
||||||
return m.isNegative(m.matchWords(headers))
|
|
||||||
} else {
|
|
||||||
return m.isNegative(m.matchWords(headers) || m.matchWords(body))
|
|
||||||
}
|
|
||||||
case RegexMatcher:
|
|
||||||
// Match the parts as required for regex check
|
|
||||||
if m.Part == "body" {
|
|
||||||
return m.isNegative(m.matchRegex(body))
|
|
||||||
} else if m.Part == "header" {
|
|
||||||
return m.isNegative(m.matchRegex(headers))
|
|
||||||
} else {
|
|
||||||
return m.isNegative(m.matchRegex(headers) || m.matchRegex(body))
|
|
||||||
}
|
|
||||||
case BinaryMatcher:
|
|
||||||
// Match the parts as required for binary characters check
|
|
||||||
if m.Part == "body" {
|
|
||||||
return m.isNegative(m.matchBinary(body))
|
|
||||||
} else if m.Part == "header" {
|
|
||||||
return m.isNegative(m.matchBinary(headers))
|
|
||||||
} else {
|
|
||||||
return m.isNegative(m.matchBinary(headers) || m.matchBinary(body))
|
|
||||||
}
|
|
||||||
case DSLMatcher:
|
|
||||||
// Match complex query
|
|
||||||
return m.isNegative(m.matchDSL(generators.MergeMaps(HTTPToMap(resp, body, headers, duration, ""), data)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
partString := part.(string)
|
||||||
|
|
||||||
// MatchDNS matches a dns response against a given matcher
|
|
||||||
func (m *Matcher) MatchDNS(msg *dns.Msg) bool {
|
|
||||||
switch m.matcherType {
|
switch m.matcherType {
|
||||||
case StatusMatcher:
|
case StatusMatcher:
|
||||||
return m.isNegative(m.matchStatusCode(msg.Rcode))
|
statusCode, ok := data["status_code"]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return m.isNegative(m.matchStatusCode(statusCode.(int)))
|
||||||
case SizeMatcher:
|
case SizeMatcher:
|
||||||
return m.matchSizeCode(msg.Len())
|
return m.isNegative(m.matchSizeCode(len(partString)))
|
||||||
case WordsMatcher:
|
case WordsMatcher:
|
||||||
// Match for word check
|
return m.isNegative(m.matchWords(partString))
|
||||||
return m.matchWords(msg.String())
|
|
||||||
case RegexMatcher:
|
case RegexMatcher:
|
||||||
// Match regex check
|
return m.isNegative(m.matchRegex(partString))
|
||||||
return m.matchRegex(msg.String())
|
|
||||||
case BinaryMatcher:
|
case BinaryMatcher:
|
||||||
// Match binary characters check
|
return m.isNegative(m.matchBinary(partString))
|
||||||
return m.matchBinary(msg.String())
|
|
||||||
case DSLMatcher:
|
case DSLMatcher:
|
||||||
// Match complex query
|
return m.isNegative(m.matchDSL(data))
|
||||||
return m.matchDSL(DNSToMap(msg, ""))
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -88,7 +47,6 @@ func (m *Matcher) matchStatusCode(statusCode int) bool {
|
||||||
// Return on the first match.
|
// Return on the first match.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,5 @@ func (m *Matcher) isNegative(data bool) bool {
|
||||||
if m.Negative {
|
if m.Negative {
|
||||||
return !data
|
return !data
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ type Operators struct {
|
||||||
// MatchersCondition is the condition of the matchers
|
// MatchersCondition is the condition of the matchers
|
||||||
// whether to use AND or OR. Default is OR.
|
// whether to use AND or OR. Default is OR.
|
||||||
MatchersCondition string `yaml:"matchers-condition"`
|
MatchersCondition string `yaml:"matchers-condition"`
|
||||||
|
|
||||||
// cached variables that may be used along with request.
|
// cached variables that may be used along with request.
|
||||||
matchersCondition matchers.ConditionType
|
matchersCondition matchers.ConditionType
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue