github.com/projectdiscovery/nuclei/v2@v2.9.15/pkg/protocols/headless/operators.go (about) 1 package headless 2 3 import ( 4 "strconv" 5 "time" 6 7 "github.com/projectdiscovery/nuclei/v2/pkg/model" 8 "github.com/projectdiscovery/nuclei/v2/pkg/operators" 9 "github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors" 10 "github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers" 11 "github.com/projectdiscovery/nuclei/v2/pkg/output" 12 "github.com/projectdiscovery/nuclei/v2/pkg/protocols" 13 "github.com/projectdiscovery/nuclei/v2/pkg/types" 14 ) 15 16 // Match matches a generic data response again a given matcher 17 func (request *Request) Match(data map[string]interface{}, matcher *matchers.Matcher) (bool, []string) { 18 itemStr, ok := request.getMatchPart(matcher.Part, data) 19 if !ok && matcher.Type.MatcherType != matchers.DSLMatcher { 20 return false, []string{} 21 } 22 23 switch matcher.GetType() { 24 case matchers.StatusMatcher: 25 statusCode, ok := getStatusCode(data) 26 if !ok { 27 return false, []string{} 28 } 29 return matcher.Result(matcher.MatchStatusCode(statusCode)), []string{} 30 case matchers.SizeMatcher: 31 return matcher.Result(matcher.MatchSize(len(itemStr))), []string{} 32 case matchers.WordsMatcher: 33 return matcher.ResultWithMatchedSnippet(matcher.MatchWords(itemStr, data)) 34 case matchers.RegexMatcher: 35 return matcher.ResultWithMatchedSnippet(matcher.MatchRegex(itemStr)) 36 case matchers.BinaryMatcher: 37 return matcher.ResultWithMatchedSnippet(matcher.MatchBinary(itemStr)) 38 case matchers.DSLMatcher: 39 return matcher.Result(matcher.MatchDSL(data)), []string{} 40 case matchers.XPathMatcher: 41 return matcher.Result(matcher.MatchXPath(itemStr)), []string{} 42 } 43 return false, []string{} 44 } 45 46 func getStatusCode(data map[string]interface{}) (int, bool) { 47 statusCodeValue, ok := data["status_code"] 48 if !ok { 49 return 0, false 50 } 51 statusCodeStr, ok := statusCodeValue.(string) 52 if !ok { 53 return 0, false 54 } 55 56 statusCode, err := strconv.Atoi(statusCodeStr) 57 if err != nil { 58 return 0, false 59 } 60 61 return statusCode, true 62 } 63 64 // Extract performs extracting operation for an extractor on model and returns true or false. 65 func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} { 66 itemStr, ok := request.getMatchPart(extractor.Part, data) 67 if !ok && !extractors.SupportsMap(extractor) { 68 return nil 69 } 70 71 switch extractor.GetType() { 72 case extractors.RegexExtractor: 73 return extractor.ExtractRegex(itemStr) 74 case extractors.KValExtractor: 75 return extractor.ExtractKval(data) 76 case extractors.DSLExtractor: 77 return extractor.ExtractDSL(data) 78 } 79 return nil 80 } 81 82 func (request *Request) getMatchPart(part string, data output.InternalEvent) (string, bool) { 83 switch part { 84 case "body", "resp", "": 85 part = "data" 86 case "history": 87 part = "history" 88 case "header": 89 part = "header" 90 } 91 92 item, ok := data[part] 93 if !ok { 94 return "", false 95 } 96 itemStr := types.ToString(item) 97 98 return itemStr, true 99 } 100 101 // responseToDSLMap converts a headless response to a map for use in DSL matching 102 func (request *Request) responseToDSLMap(resp, headers, status_code, req, host, matched string, history string) output.InternalEvent { 103 return 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 } 117 118 // MakeResultEvent creates a result event from internal wrapped event 119 func (request *Request) MakeResultEvent(wrapped *output.InternalWrappedEvent) []*output.ResultEvent { 120 return protocols.MakeDefaultResultEvent(request, wrapped) 121 } 122 123 func (request *Request) GetCompiledOperators() []*operators.Operators { 124 return []*operators.Operators{request.CompiledOperators} 125 } 126 127 func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent) *output.ResultEvent { 128 data := &output.ResultEvent{ 129 TemplateID: types.ToString(wrapped.InternalEvent["template-id"]), 130 TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]), 131 Info: wrapped.InternalEvent["template-info"].(model.Info), 132 Type: types.ToString(wrapped.InternalEvent["type"]), 133 Host: types.ToString(wrapped.InternalEvent["host"]), 134 Matched: types.ToString(wrapped.InternalEvent["matched"]), 135 ExtractedResults: wrapped.OperatorsResult.OutputExtracts, 136 Timestamp: time.Now(), 137 MatcherStatus: true, 138 IP: types.ToString(wrapped.InternalEvent["ip"]), 139 Request: types.ToString(wrapped.InternalEvent["request"]), 140 Response: types.ToString(wrapped.InternalEvent["data"]), 141 } 142 return data 143 }