mirror of https://github.com/daffainfo/nuclei.git
Replacing expression regex with lexical analyzer (#1440)
* Replacing regex with lexical analyzer taken from 610beb8534/v2/pkg/protocols/common/expressions/expressions.go (L66)
dev
parent
39519c01a6
commit
0e8270c7b5
|
@ -1,17 +1,16 @@
|
||||||
package expressions
|
package expressions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"strings"
|
||||||
|
|
||||||
"github.com/Knetic/govaluate"
|
"github.com/Knetic/govaluate"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/operators/common/dsl"
|
"github.com/projectdiscovery/nuclei/v2/pkg/operators/common/dsl"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/marker"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/replacer"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/replacer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var templateExpressionRegex = regexp.MustCompile(`(?m){{[^}]+}}["')}]*`)
|
|
||||||
|
|
||||||
// Evaluate checks if the match contains a dynamic variable, for each
|
// Evaluate checks if the match contains a dynamic variable, for each
|
||||||
// found one we will check if it's an expression and can
|
// found one we will check if it's an expression and can
|
||||||
// be compiled, it will be evaluated and the results will be returned.
|
// be compiled, it will be evaluated and the results will be returned.
|
||||||
|
@ -37,7 +36,7 @@ func evaluate(data string, base map[string]interface{}) (string, error) {
|
||||||
data = replacer.Replace(data, base)
|
data = replacer.Replace(data, base)
|
||||||
|
|
||||||
dynamicValues := make(map[string]interface{})
|
dynamicValues := make(map[string]interface{})
|
||||||
for _, match := range templateExpressionRegex.FindAllString(data, -1) {
|
for _, match := range findMatches(data) {
|
||||||
expr := generators.TrimDelimiters(match)
|
expr := generators.TrimDelimiters(match)
|
||||||
|
|
||||||
compiled, err := govaluate.NewEvaluableExpressionWithFunctions(expr, dsl.HelperFunctions())
|
compiled, err := govaluate.NewEvaluableExpressionWithFunctions(expr, dsl.HelperFunctions())
|
||||||
|
@ -53,3 +52,14 @@ func evaluate(data string, base map[string]interface{}) (string, error) {
|
||||||
// Replacer dynamic values if any in raw request and parse it
|
// Replacer dynamic values if any in raw request and parse it
|
||||||
return replacer.Replace(data, dynamicValues), nil
|
return replacer.Replace(data, dynamicValues), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findMatches(data string) []string {
|
||||||
|
var matches []string
|
||||||
|
for _, token := range strings.Split(data, marker.ParenthesisOpen) {
|
||||||
|
closingToken := strings.LastIndex(token, marker.ParenthesisClose)
|
||||||
|
if closingToken > 0 {
|
||||||
|
matches = append(matches, token[:closingToken])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|
|
@ -12,12 +12,15 @@ func TestEvaluate(t *testing.T) {
|
||||||
expected string
|
expected string
|
||||||
extra map[string]interface{}
|
extra map[string]interface{}
|
||||||
}{
|
}{
|
||||||
|
{input: "{{url_encode('test}aaa')}}", expected: "test%7Daaa", extra: map[string]interface{}{}},
|
||||||
{input: "{{hex_encode('PING')}}", expected: "50494e47", extra: map[string]interface{}{}},
|
{input: "{{hex_encode('PING')}}", expected: "50494e47", extra: map[string]interface{}{}},
|
||||||
{input: "test", expected: "test", extra: map[string]interface{}{}},
|
{input: "test", expected: "test", extra: map[string]interface{}{}},
|
||||||
{input: "{{hex_encode(Item)}}", expected: "50494e47", extra: map[string]interface{}{"Item": "PING"}},
|
{input: "{{hex_encode(Item)}}", expected: "50494e47", extra: map[string]interface{}{"Item": "PING"}},
|
||||||
{input: "{{hex_encode(Item)}}\r\n", expected: "50494e47\r\n", extra: map[string]interface{}{"Item": "PING"}},
|
{input: "{{hex_encode(Item)}}\r\n", expected: "50494e47\r\n", extra: map[string]interface{}{"Item": "PING"}},
|
||||||
{input: "{{someTestData}}{{hex_encode('PING')}}", expected: "{{someTestData}}50494e47", extra: map[string]interface{}{}},
|
{input: "{{someTestData}}{{hex_encode('PING')}}", expected: "{{someTestData}}50494e47", extra: map[string]interface{}{}},
|
||||||
{input: `_IWP_JSON_PREFIX_{{base64("{\"iwp_action\":\"add_site\",\"params\":{\"username\":\"\"}}")}}`, expected: "_IWP_JSON_PREFIX_eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiIifX0=", extra: map[string]interface{}{}},
|
{input: `_IWP_JSON_PREFIX_{{base64("{\"iwp_action\":\"add_site\",\"params\":{\"username\":\"\"}}")}}`, expected: "_IWP_JSON_PREFIX_eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiIifX0=", extra: map[string]interface{}{}},
|
||||||
|
{input: "{{}}", expected: "{{}}", extra: map[string]interface{}{}},
|
||||||
|
{input: `"{{hex_encode('PING')}}"`, expected: `"50494e47"`, extra: map[string]interface{}{}},
|
||||||
}
|
}
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
value, err := Evaluate(item.input, item.extra)
|
value, err := Evaluate(item.input, item.extra)
|
||||||
|
|
|
@ -3,6 +3,8 @@ package generators
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/marker"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MergeMapsMany merges many maps into a new map
|
// MergeMapsMany merges many maps into a new map
|
||||||
|
@ -85,5 +87,5 @@ func CopyMapWithDefaultValue(originalMap map[string][]string, defaultValue inter
|
||||||
|
|
||||||
// TrimDelimiters removes trailing brackets
|
// TrimDelimiters removes trailing brackets
|
||||||
func TrimDelimiters(s string) string {
|
func TrimDelimiters(s string) string {
|
||||||
return strings.TrimSuffix(strings.TrimPrefix(s, "{{"), "}}")
|
return strings.TrimSuffix(strings.TrimPrefix(s, marker.ParenthesisOpen), marker.ParenthesisClose)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package marker
|
||||||
|
|
||||||
|
const (
|
||||||
|
// General marker (open/close)
|
||||||
|
General = "§"
|
||||||
|
// ParenthesisOpen marker - begin of a placeholder
|
||||||
|
ParenthesisOpen = "{{"
|
||||||
|
// ParenthesisClose marker - end of a placeholder
|
||||||
|
ParenthesisClose = "}}"
|
||||||
|
)
|
|
@ -3,32 +3,26 @@ package replacer
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/marker"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Payload marker constants
|
|
||||||
const (
|
|
||||||
MarkerGeneral = "§"
|
|
||||||
MarkerParenthesisOpen = "{{"
|
|
||||||
MarkerParenthesisClose = "}}"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Replace replaces placeholders in template with values on the fly.
|
// Replace replaces placeholders in template with values on the fly.
|
||||||
func Replace(template string, values map[string]interface{}) string {
|
func Replace(template string, values map[string]interface{}) string {
|
||||||
var replacerItems []string
|
var replacerItems []string
|
||||||
|
|
||||||
builder := &strings.Builder{}
|
builder := &strings.Builder{}
|
||||||
for key, val := range values {
|
for key, val := range values {
|
||||||
builder.WriteString(MarkerParenthesisOpen)
|
builder.WriteString(marker.ParenthesisOpen)
|
||||||
builder.WriteString(key)
|
builder.WriteString(key)
|
||||||
builder.WriteString(MarkerParenthesisClose)
|
builder.WriteString(marker.ParenthesisClose)
|
||||||
replacerItems = append(replacerItems, builder.String())
|
replacerItems = append(replacerItems, builder.String())
|
||||||
builder.Reset()
|
builder.Reset()
|
||||||
replacerItems = append(replacerItems, types.ToString(val))
|
replacerItems = append(replacerItems, types.ToString(val))
|
||||||
|
|
||||||
builder.WriteString(MarkerGeneral)
|
builder.WriteString(marker.General)
|
||||||
builder.WriteString(key)
|
builder.WriteString(key)
|
||||||
builder.WriteString(MarkerGeneral)
|
builder.WriteString(marker.General)
|
||||||
replacerItems = append(replacerItems, builder.String())
|
replacerItems = append(replacerItems, builder.String())
|
||||||
builder.Reset()
|
builder.Reset()
|
||||||
replacerItems = append(replacerItems, types.ToString(val))
|
replacerItems = append(replacerItems, types.ToString(val))
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/go-rod/rod/lib/proto"
|
"github.com/go-rod/rod/lib/proto"
|
||||||
"github.com/go-rod/rod/lib/utils"
|
"github.com/go-rod/rod/lib/utils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/marker"
|
||||||
"github.com/segmentio/ksuid"
|
"github.com/segmentio/ksuid"
|
||||||
"github.com/valyala/fasttemplate"
|
"github.com/valyala/fasttemplate"
|
||||||
)
|
)
|
||||||
|
@ -254,7 +255,7 @@ func (p *Page) NavigateURL(action *Action, out map[string]string, parsed *url.UR
|
||||||
parsedString := parsed.String()
|
parsedString := parsed.String()
|
||||||
values["BaseURL"] = parsedString
|
values["BaseURL"] = parsedString
|
||||||
|
|
||||||
final := fasttemplate.ExecuteStringStd(URL, "{{", "}}", values)
|
final := fasttemplate.ExecuteStringStd(URL, marker.ParenthesisOpen, marker.ParenthesisClose, values)
|
||||||
if err := p.page.Navigate(final); err != nil {
|
if err := p.page.Navigate(final); err != nil {
|
||||||
return errors.Wrap(err, "could not navigate")
|
return errors.Wrap(err, "could not navigate")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue