Path: blob/dev/pkg/protocols/headless/operators.go
2070 views
package headless12import (3"strconv"4"time"56"github.com/projectdiscovery/nuclei/v3/pkg/model"7"github.com/projectdiscovery/nuclei/v3/pkg/operators"8"github.com/projectdiscovery/nuclei/v3/pkg/operators/extractors"9"github.com/projectdiscovery/nuclei/v3/pkg/operators/matchers"10"github.com/projectdiscovery/nuclei/v3/pkg/output"11"github.com/projectdiscovery/nuclei/v3/pkg/protocols"12protocolUtils "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"13"github.com/projectdiscovery/nuclei/v3/pkg/types"14)1516// Match matches a generic data response again a given matcher17func (request *Request) Match(data map[string]interface{}, matcher *matchers.Matcher) (bool, []string) {18itemStr, ok := request.getMatchPart(matcher.Part, data)19if !ok && matcher.Type.MatcherType != matchers.DSLMatcher {20return false, []string{}21}2223switch matcher.GetType() {24case matchers.StatusMatcher:25statusCode, ok := getStatusCode(data)26if !ok {27return false, []string{}28}29return matcher.Result(matcher.MatchStatusCode(statusCode)), []string{}30case matchers.SizeMatcher:31return matcher.Result(matcher.MatchSize(len(itemStr))), []string{}32case matchers.WordsMatcher:33return matcher.ResultWithMatchedSnippet(matcher.MatchWords(itemStr, data))34case matchers.RegexMatcher:35return matcher.ResultWithMatchedSnippet(matcher.MatchRegex(itemStr))36case matchers.BinaryMatcher:37return matcher.ResultWithMatchedSnippet(matcher.MatchBinary(itemStr))38case matchers.DSLMatcher:39return matcher.Result(matcher.MatchDSL(data)), []string{}40case matchers.XPathMatcher:41return matcher.Result(matcher.MatchXPath(itemStr)), []string{}42}43return false, []string{}44}4546func getStatusCode(data map[string]interface{}) (int, bool) {47statusCodeValue, ok := data["status_code"]48if !ok {49return 0, false50}51statusCodeStr, ok := statusCodeValue.(string)52if !ok {53return 0, false54}5556statusCode, err := strconv.Atoi(statusCodeStr)57if err != nil {58return 0, false59}6061return statusCode, true62}6364// Extract performs extracting operation for an extractor on model and returns true or false.65func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {66itemStr, ok := request.getMatchPart(extractor.Part, data)67if !ok && !extractors.SupportsMap(extractor) {68return nil69}7071switch extractor.GetType() {72case extractors.RegexExtractor:73return extractor.ExtractRegex(itemStr)74case extractors.KValExtractor:75return extractor.ExtractKval(data)76case extractors.DSLExtractor:77return extractor.ExtractDSL(data)78}79return nil80}8182func (request *Request) getMatchPart(part string, data output.InternalEvent) (string, bool) {83switch part {84case "body", "resp", "":85part = "data"86case "history":87part = "history"88case "header":89part = "header"90}9192item, ok := data[part]93if !ok {94return "", false95}96itemStr := types.ToString(item)9798return itemStr, true99}100101// responseToDSLMap converts a headless response to a map for use in DSL matching102func (request *Request) responseToDSLMap(resp, headers, status_code, req, host, matched string, history string) output.InternalEvent {103return output.InternalEvent{104"host": host,105"matched": matched,106"req": req,107"data": resp,108"header": headers,109"status_code": status_code,110"history": history,111"type": request.Type().String(),112"template-id": request.options.TemplateID,113"template-info": request.options.TemplateInfo,114"template-path": request.options.TemplatePath,115}116}117118// MakeResultEvent creates a result event from internal wrapped event119func (request *Request) MakeResultEvent(wrapped *output.InternalWrappedEvent) []*output.ResultEvent {120return protocols.MakeDefaultResultEvent(request, wrapped)121}122123func (request *Request) GetCompiledOperators() []*operators.Operators {124return []*operators.Operators{request.CompiledOperators}125}126127func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent) *output.ResultEvent {128fields := protocolUtils.GetJsonFieldsFromURL(types.ToString(wrapped.InternalEvent["host"]))129if types.ToString(wrapped.InternalEvent["ip"]) != "" {130fields.Ip = types.ToString(wrapped.InternalEvent["ip"])131}132if types.ToString(wrapped.InternalEvent["path"]) != "" {133fields.Path = types.ToString(wrapped.InternalEvent["path"])134}135data := &output.ResultEvent{136TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),137TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),138Info: wrapped.InternalEvent["template-info"].(model.Info),139TemplateVerifier: request.options.TemplateVerifier,140Type: types.ToString(wrapped.InternalEvent["type"]),141Host: fields.Host,142Path: fields.Path,143Port: fields.Port,144Scheme: fields.Scheme,145URL: fields.URL,146Matched: types.ToString(wrapped.InternalEvent["matched"]),147ExtractedResults: wrapped.OperatorsResult.OutputExtracts,148Timestamp: time.Now(),149MatcherStatus: true,150IP: fields.Ip,151Request: types.ToString(wrapped.InternalEvent["request"]),152Response: types.ToString(wrapped.InternalEvent["data"]),153TemplateEncoded: request.options.EncodeTemplate(),154Error: types.ToString(wrapped.InternalEvent["error"]),155}156return data157}158159160