mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 21:25:27 +00:00
adding support for dsl extractors
This commit is contained in:
parent
3bbce299ae
commit
72c5c399ec
@ -5,7 +5,9 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Knetic/govaluate"
|
||||||
"github.com/itchyny/gojq"
|
"github.com/itchyny/gojq"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/operators/common/dsl"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CompileExtractors performs the initial setup operation on an extractor
|
// CompileExtractors performs the initial setup operation on an extractor
|
||||||
@ -40,6 +42,14 @@ func (e *Extractor) CompileExtractors() error {
|
|||||||
e.jsonCompiled = append(e.jsonCompiled, compiled)
|
e.jsonCompiled = append(e.jsonCompiled, compiled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, dslExp := range e.DSL {
|
||||||
|
compiled, err := govaluate.NewEvaluableExpressionWithFunctions(dslExp, dsl.HelperFunctions())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not compile dsl: %s", dslExp)
|
||||||
|
}
|
||||||
|
e.dslCompiled = append(e.dslCompiled, compiled)
|
||||||
|
}
|
||||||
|
|
||||||
if e.CaseInsensitive {
|
if e.CaseInsensitive {
|
||||||
if e.GetType() != KValExtractor {
|
if e.GetType() != KValExtractor {
|
||||||
return fmt.Errorf("case-insensitive flag is supported only for 'kval' extractors (not '%s')", e.Type)
|
return fmt.Errorf("case-insensitive flag is supported only for 'kval' extractors (not '%s')", e.Type)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package extractors
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/antchfx/htmlquery"
|
"github.com/antchfx/htmlquery"
|
||||||
@ -122,3 +123,24 @@ func (e *Extractor) ExtractJSON(corpus string) map[string]struct{} {
|
|||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtractDSL execute the expression and returns the results
|
||||||
|
func (e *Extractor) ExtractDSL(data map[string]interface{}) map[string]struct{} {
|
||||||
|
results := make(map[string]struct{})
|
||||||
|
|
||||||
|
for _, compiledExpression := range e.dslCompiled {
|
||||||
|
result, err := compiledExpression.Evaluate(data)
|
||||||
|
if err != nil {
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
if result != nil {
|
||||||
|
resultString := fmt.Sprint(result)
|
||||||
|
if resultString != "" {
|
||||||
|
results[resultString] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|||||||
@ -21,6 +21,8 @@ const (
|
|||||||
XPathExtractor
|
XPathExtractor
|
||||||
// name:json
|
// name:json
|
||||||
JSONExtractor
|
JSONExtractor
|
||||||
|
// name:dsl
|
||||||
|
DSLExtractor
|
||||||
limit
|
limit
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,6 +32,7 @@ var extractorMappings = map[ExtractorType]string{
|
|||||||
KValExtractor: "kval",
|
KValExtractor: "kval",
|
||||||
XPathExtractor: "xpath",
|
XPathExtractor: "xpath",
|
||||||
JSONExtractor: "json",
|
JSONExtractor: "json",
|
||||||
|
DSLExtractor: "dsl",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetType returns the type of the matcher
|
// GetType returns the type of the matcher
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package extractors
|
|||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/Knetic/govaluate"
|
||||||
"github.com/itchyny/gojq"
|
"github.com/itchyny/gojq"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -87,6 +88,11 @@ type Extractor struct {
|
|||||||
// jsonCompiled is the compiled variant
|
// jsonCompiled is the compiled variant
|
||||||
jsonCompiled []*gojq.Code
|
jsonCompiled []*gojq.Code
|
||||||
|
|
||||||
|
// description: |
|
||||||
|
// Extracts using DSL expressions.
|
||||||
|
DSL []string
|
||||||
|
dslCompiled []*govaluate.EvaluableExpression
|
||||||
|
|
||||||
// description: |
|
// description: |
|
||||||
// Part is the part of the request response to extract data from.
|
// Part is the part of the request response to extract data from.
|
||||||
//
|
//
|
||||||
|
|||||||
6
v2/pkg/operators/extractors/util.go
Normal file
6
v2/pkg/operators/extractors/util.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package extractors
|
||||||
|
|
||||||
|
// SupportsMap determines if the extractor type requires a map
|
||||||
|
func SupportsMap(extractor *Extractor) bool {
|
||||||
|
return extractor.Type.ExtractorType == KValExtractor || extractor.Type.ExtractorType == DSLExtractor
|
||||||
|
}
|
||||||
@ -48,7 +48,7 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat
|
|||||||
// Extract performs extracting operation for an extractor on model and returns true or false.
|
// Extract performs extracting operation for an extractor on model and returns true or false.
|
||||||
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
||||||
item, ok := request.getMatchPart(extractor.Part, data)
|
item, ok := request.getMatchPart(extractor.Part, data)
|
||||||
if !ok && extractor.Type.ExtractorType != extractors.KValExtractor {
|
if !ok && !extractors.SupportsMap(extractor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +57,8 @@ func (request *Request) Extract(data map[string]interface{}, extractor *extracto
|
|||||||
return extractor.ExtractRegex(types.ToString(item))
|
return extractor.ExtractRegex(types.ToString(item))
|
||||||
case extractors.KValExtractor:
|
case extractors.KValExtractor:
|
||||||
return extractor.ExtractKval(data)
|
return extractor.ExtractKval(data)
|
||||||
|
case extractors.DSLExtractor:
|
||||||
|
return extractor.ExtractDSL(data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat
|
|||||||
// Extract performs extracting operation for an extractor on model and returns true or false.
|
// Extract performs extracting operation for an extractor on model and returns true or false.
|
||||||
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
||||||
itemStr, ok := request.getMatchPart(extractor.Part, data)
|
itemStr, ok := request.getMatchPart(extractor.Part, data)
|
||||||
if !ok && extractor.Type.ExtractorType != extractors.KValExtractor {
|
if !ok && !extractors.SupportsMap(extractor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +46,8 @@ func (request *Request) Extract(data map[string]interface{}, extractor *extracto
|
|||||||
return extractor.ExtractRegex(itemStr)
|
return extractor.ExtractRegex(itemStr)
|
||||||
case extractors.KValExtractor:
|
case extractors.KValExtractor:
|
||||||
return extractor.ExtractKval(data)
|
return extractor.ExtractKval(data)
|
||||||
|
case extractors.DSLExtractor:
|
||||||
|
return extractor.ExtractDSL(data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat
|
|||||||
// Extract performs extracting operation for an extractor on model and returns true or false.
|
// Extract performs extracting operation for an extractor on model and returns true or false.
|
||||||
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
||||||
itemStr, ok := request.getMatchPart(extractor.Part, data)
|
itemStr, ok := request.getMatchPart(extractor.Part, data)
|
||||||
if !ok && extractor.Type.ExtractorType != extractors.KValExtractor {
|
if !ok && !extractors.SupportsMap(extractor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +46,8 @@ func (request *Request) Extract(data map[string]interface{}, extractor *extracto
|
|||||||
return extractor.ExtractRegex(itemStr)
|
return extractor.ExtractRegex(itemStr)
|
||||||
case extractors.KValExtractor:
|
case extractors.KValExtractor:
|
||||||
return extractor.ExtractKval(data)
|
return extractor.ExtractKval(data)
|
||||||
|
case extractors.DSLExtractor:
|
||||||
|
return extractor.ExtractDSL(data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@ func getStatusCode(data map[string]interface{}) (int, bool) {
|
|||||||
// Extract performs extracting operation for an extractor on model and returns true or false.
|
// Extract performs extracting operation for an extractor on model and returns true or false.
|
||||||
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
||||||
item, ok := request.getMatchPart(extractor.Part, data)
|
item, ok := request.getMatchPart(extractor.Part, data)
|
||||||
if !ok && extractor.Type.ExtractorType != extractors.KValExtractor {
|
if !ok && !extractors.SupportsMap(extractor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch extractor.GetType() {
|
switch extractor.GetType() {
|
||||||
@ -70,6 +70,8 @@ func (request *Request) Extract(data map[string]interface{}, extractor *extracto
|
|||||||
return extractor.ExtractHTML(item)
|
return extractor.ExtractHTML(item)
|
||||||
case extractors.JSONExtractor:
|
case extractors.JSONExtractor:
|
||||||
return extractor.ExtractJSON(item)
|
return extractor.ExtractJSON(item)
|
||||||
|
case extractors.DSLExtractor:
|
||||||
|
return extractor.ExtractDSL(data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat
|
|||||||
// Extract performs extracting operation for an extractor on model and returns true or false.
|
// Extract performs extracting operation for an extractor on model and returns true or false.
|
||||||
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
||||||
itemStr, ok := request.getMatchPart(extractor.Part, data)
|
itemStr, ok := request.getMatchPart(extractor.Part, data)
|
||||||
if !ok && extractor.Type.ExtractorType != extractors.KValExtractor {
|
if !ok && !extractors.SupportsMap(extractor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +46,8 @@ func (request *Request) Extract(data map[string]interface{}, extractor *extracto
|
|||||||
return extractor.ExtractRegex(itemStr)
|
return extractor.ExtractRegex(itemStr)
|
||||||
case extractors.KValExtractor:
|
case extractors.KValExtractor:
|
||||||
return extractor.ExtractKval(data)
|
return extractor.ExtractKval(data)
|
||||||
|
case extractors.DSLExtractor:
|
||||||
|
return extractor.ExtractDSL(data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@ func getStatusCode(data map[string]interface{}) (int, bool) {
|
|||||||
// Extract performs extracting operation for an extractor on model and returns true or false.
|
// Extract performs extracting operation for an extractor on model and returns true or false.
|
||||||
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
func (request *Request) Extract(data map[string]interface{}, extractor *extractors.Extractor) map[string]struct{} {
|
||||||
item, ok := getMatchPart(extractor.Part, data)
|
item, ok := getMatchPart(extractor.Part, data)
|
||||||
if !ok && extractor.Type.ExtractorType != extractors.KValExtractor {
|
if !ok && !extractors.SupportsMap(extractor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch extractor.GetType() {
|
switch extractor.GetType() {
|
||||||
@ -66,6 +66,8 @@ func (request *Request) Extract(data map[string]interface{}, extractor *extracto
|
|||||||
return extractor.ExtractRegex(item)
|
return extractor.ExtractRegex(item)
|
||||||
case extractors.KValExtractor:
|
case extractors.KValExtractor:
|
||||||
return extractor.ExtractKval(data)
|
return extractor.ExtractKval(data)
|
||||||
|
case extractors.DSLExtractor:
|
||||||
|
return extractor.ExtractDSL(data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,7 +144,7 @@ func MakeDefaultExtractFunc(data map[string]interface{}, extractor *extractors.E
|
|||||||
}
|
}
|
||||||
|
|
||||||
item, ok := data[part]
|
item, ok := data[part]
|
||||||
if !ok && extractor.Type.ExtractorType != extractors.KValExtractor {
|
if !ok && !extractors.SupportsMap(extractor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
itemStr := types.ToString(item)
|
itemStr := types.ToString(item)
|
||||||
@ -158,6 +158,8 @@ func MakeDefaultExtractFunc(data map[string]interface{}, extractor *extractors.E
|
|||||||
return extractor.ExtractJSON(itemStr)
|
return extractor.ExtractJSON(itemStr)
|
||||||
case extractors.XPathExtractor:
|
case extractors.XPathExtractor:
|
||||||
return extractor.ExtractHTML(itemStr)
|
return extractor.ExtractHTML(itemStr)
|
||||||
|
case extractors.DSLExtractor:
|
||||||
|
return extractor.ExtractDSL(data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user