288 lines
8.4 KiB
Go
Raw Normal View History

2020-12-22 03:54:55 +05:30
package dsl
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
2020-10-16 14:18:50 +02:00
"fmt"
"html"
2020-10-11 20:26:27 +02:00
"math"
"math/rand"
"net/url"
"regexp"
"strings"
2020-10-23 10:13:34 +02:00
"time"
2020-10-16 22:27:25 +02:00
"github.com/Knetic/govaluate"
2021-08-23 19:25:11 +07:00
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/deserialization"
2020-12-24 12:13:18 +05:30
"github.com/projectdiscovery/nuclei/v2/pkg/types"
2020-10-16 13:27:02 +02:00
"github.com/spaolacci/murmur3"
)
2020-10-16 22:07:00 +02:00
const (
2020-12-22 03:54:55 +05:30
numbers = "1234567890"
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
2020-10-16 22:07:00 +02:00
withCutSetArgsSize = 2
withBaseRandArgsSize = 3
2020-12-22 03:54:55 +05:30
withMaxRandArgsSize = withCutSetArgsSize
2020-10-16 22:07:00 +02:00
)
2021-07-20 23:27:12 -07:00
var functions = map[string]govaluate.ExpressionFunction{
"len": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
length := len(types.ToString(args[0]))
return float64(length), nil
2021-07-20 23:27:12 -07:00
},
"toupper": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.ToUpper(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
"tolower": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.ToLower(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
"replace": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.ReplaceAll(types.ToString(args[0]), types.ToString(args[1]), types.ToString(args[2])), nil
2021-07-20 23:27:12 -07:00
},
"replace_regex": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
compiled, err := regexp.Compile(types.ToString(args[1]))
if err != nil {
return nil, err
}
2020-12-24 12:13:18 +05:30
return compiled.ReplaceAllString(types.ToString(args[0]), types.ToString(args[2])), nil
2021-07-20 23:27:12 -07:00
},
"trim": func(args ...interface{}) (interface{}, error) {
2021-08-17 14:06:49 +02:00
return strings.Trim(types.ToString(args[0]), types.ToString(args[1])), nil
2021-07-20 23:27:12 -07:00
},
"trimleft": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.TrimLeft(types.ToString(args[0]), types.ToString(args[1])), nil
2021-07-20 23:27:12 -07:00
},
"trimright": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.TrimRight(types.ToString(args[0]), types.ToString(args[1])), nil
2021-07-20 23:27:12 -07:00
},
"trimspace": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.TrimSpace(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
"trimprefix": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.TrimPrefix(types.ToString(args[0]), types.ToString(args[1])), nil
2021-07-20 23:27:12 -07:00
},
"trimsuffix": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.TrimSuffix(types.ToString(args[0]), types.ToString(args[1])), nil
2021-07-20 23:27:12 -07:00
},
"reverse": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return reverseString(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
// encoding
2021-07-20 23:27:12 -07:00
"base64": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
sEnc := base64.StdEncoding.EncodeToString([]byte(types.ToString(args[0])))
return sEnc, nil
2021-07-20 23:27:12 -07:00
},
2020-10-16 13:27:02 +02:00
// python encodes to base64 with lines of 76 bytes terminated by new line "\n"
2021-07-20 23:27:12 -07:00
"base64_py": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
sEnc := base64.StdEncoding.EncodeToString([]byte(types.ToString(args[0])))
return deserialization.InsertInto(sEnc, 76, '\n'), nil
2021-07-20 23:27:12 -07:00
},
"base64_decode": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return base64.StdEncoding.DecodeString(types.ToString(args[0]))
2021-07-20 23:27:12 -07:00
},
"url_encode": func(args ...interface{}) (interface{}, error) {
return url.QueryEscape(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
"url_decode": func(args ...interface{}) (interface{}, error) {
return url.QueryUnescape(types.ToString(args[0]))
2021-07-20 23:27:12 -07:00
},
"hex_encode": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return hex.EncodeToString([]byte(types.ToString(args[0]))), nil
2021-07-20 23:27:12 -07:00
},
"hex_decode": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
hx, _ := hex.DecodeString(types.ToString(args[0]))
return string(hx), nil
2021-07-20 23:27:12 -07:00
},
"html_escape": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return html.EscapeString(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
"html_unescape": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return html.UnescapeString(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
// hashing
2021-07-20 23:27:12 -07:00
"md5": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
hash := md5.Sum([]byte(types.ToString(args[0])))
return hex.EncodeToString(hash[:]), nil
2021-07-20 23:27:12 -07:00
},
"sha256": func(args ...interface{}) (interface{}, error) {
h := sha256.New()
if _, err := h.Write([]byte(types.ToString(args[0]))); err != nil {
return nil, err
}
return hex.EncodeToString(h.Sum(nil)), nil
2021-07-20 23:27:12 -07:00
},
"sha1": func(args ...interface{}) (interface{}, error) {
h := sha1.New()
if _, err := h.Write([]byte(types.ToString(args[0]))); err != nil {
return nil, err
}
return hex.EncodeToString(h.Sum(nil)), nil
2021-07-20 23:27:12 -07:00
},
"mmh3": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return fmt.Sprintf("%d", int32(murmur3.Sum32WithSeed([]byte(types.ToString(args[0])), 0))), nil
2021-07-20 23:27:12 -07:00
},
// search
2021-07-20 23:27:12 -07:00
"contains": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return strings.Contains(types.ToString(args[0]), types.ToString(args[1])), nil
2021-07-20 23:27:12 -07:00
},
"regex": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
compiled, err := regexp.Compile(types.ToString(args[0]))
if err != nil {
return nil, err
}
2020-12-24 12:13:18 +05:30
return compiled.MatchString(types.ToString(args[1])), nil
2021-07-20 23:27:12 -07:00
},
2020-10-11 20:26:27 +02:00
// random generators
2021-07-20 23:27:12 -07:00
"rand_char": func(args ...interface{}) (interface{}, error) {
2020-10-11 20:26:27 +02:00
chars := letters + numbers
bad := ""
if len(args) >= 1 {
2020-12-24 12:13:18 +05:30
chars = types.ToString(args[0])
2020-10-11 20:26:27 +02:00
}
2020-10-16 22:07:00 +02:00
if len(args) >= withCutSetArgsSize {
2020-12-24 12:13:18 +05:30
bad = types.ToString(args[1])
2020-10-11 20:26:27 +02:00
}
2020-12-22 03:54:55 +05:30
chars = trimAll(chars, bad)
2020-10-11 20:26:27 +02:00
return chars[rand.Intn(len(chars))], nil
2021-07-20 23:27:12 -07:00
},
"rand_base": func(args ...interface{}) (interface{}, error) {
2020-10-11 20:26:27 +02:00
l := 0
bad := ""
base := letters + numbers
if len(args) >= 1 {
2021-08-17 14:14:47 +02:00
l = int(args[0].(float64))
2020-10-11 20:26:27 +02:00
}
2020-10-16 22:07:00 +02:00
if len(args) >= withCutSetArgsSize {
2020-12-24 12:13:18 +05:30
bad = types.ToString(args[1])
2020-10-11 20:26:27 +02:00
}
2020-10-16 22:07:00 +02:00
if len(args) >= withBaseRandArgsSize {
2020-12-24 12:13:18 +05:30
base = types.ToString(args[2])
2020-10-11 20:26:27 +02:00
}
2020-12-22 03:54:55 +05:30
base = trimAll(base, bad)
return randSeq(base, l), nil
2021-07-20 23:27:12 -07:00
},
"rand_text_alphanumeric": func(args ...interface{}) (interface{}, error) {
2020-10-11 20:26:27 +02:00
l := 0
bad := ""
chars := letters + numbers
if len(args) >= 1 {
2021-08-17 14:14:47 +02:00
l = int(args[0].(float64))
2020-10-11 20:26:27 +02:00
}
2020-10-16 22:07:00 +02:00
if len(args) >= withCutSetArgsSize {
2020-12-24 12:13:18 +05:30
bad = types.ToString(args[1])
2020-10-11 20:26:27 +02:00
}
2020-12-22 03:54:55 +05:30
chars = trimAll(chars, bad)
return randSeq(chars, l), nil
2021-07-20 23:27:12 -07:00
},
"rand_text_alpha": func(args ...interface{}) (interface{}, error) {
2020-10-11 20:26:27 +02:00
l := 0
bad := ""
chars := letters
if len(args) >= 1 {
2021-08-17 14:14:47 +02:00
l = int(args[0].(float64))
2020-10-11 20:26:27 +02:00
}
2020-10-16 22:07:00 +02:00
if len(args) >= withCutSetArgsSize {
2020-12-24 12:13:18 +05:30
bad = types.ToString(args[1])
2020-10-11 20:26:27 +02:00
}
2020-12-22 03:54:55 +05:30
chars = trimAll(chars, bad)
return randSeq(chars, l), nil
2021-07-20 23:27:12 -07:00
},
"rand_text_numeric": func(args ...interface{}) (interface{}, error) {
2020-10-11 20:26:27 +02:00
l := 0
bad := ""
chars := numbers
if len(args) >= 1 {
2021-08-17 14:14:47 +02:00
l = int(args[0].(float64))
2020-10-11 20:26:27 +02:00
}
2020-10-16 22:07:00 +02:00
if len(args) >= withCutSetArgsSize {
2020-12-24 12:13:18 +05:30
bad = types.ToString(args[1])
2020-10-11 20:26:27 +02:00
}
2020-12-22 03:54:55 +05:30
chars = trimAll(chars, bad)
return randSeq(chars, l), nil
2021-07-20 23:27:12 -07:00
},
"rand_int": func(args ...interface{}) (interface{}, error) {
2020-10-11 20:26:27 +02:00
min := 0
max := math.MaxInt32
if len(args) >= 1 {
min = int(args[0].(float64))
2020-10-11 20:26:27 +02:00
}
2020-10-16 22:07:00 +02:00
if len(args) >= withMaxRandArgsSize {
max = int(args[1].(float64))
2020-10-11 20:26:27 +02:00
}
return rand.Intn(max-min) + min, nil
2021-07-20 23:27:12 -07:00
},
2020-10-23 10:13:34 +02:00
// Time Functions
2021-07-20 23:27:12 -07:00
"waitfor": func(args ...interface{}) (interface{}, error) {
2020-10-23 10:13:34 +02:00
seconds := args[0].(float64)
time.Sleep(time.Duration(seconds) * time.Second)
return true, nil
2021-07-20 23:27:12 -07:00
},
// deserialization Functions
2021-07-24 19:27:09 +05:30
"generate_java_gadget": func(args ...interface{}) (interface{}, error) {
gadget := args[0].(string)
cmd := args[1].(string)
var encoding string
if len(args) > 2 {
encoding = args[2].(string)
}
data := deserialization.GenerateJavaGadget(gadget, cmd, encoding)
return data, nil
},
// for debug purposes
2021-08-23 19:18:07 +07:00
"print_debug": func(args ...interface{}) (interface{}, error) {
gologger.Info().Msgf("print_debug value: %s", fmt.Sprint(args))
return true, nil
},
2021-07-20 23:27:12 -07:00
}
// HelperFunctions returns the dsl helper functions
2021-07-20 23:27:12 -07:00
func HelperFunctions() map[string]govaluate.ExpressionFunction {
return functions
}
2020-12-22 03:54:55 +05:30
2021-08-31 13:21:15 +03:00
// AddHelperFunction allows creation of additional helper functions to be supported with templates
func AddHelperFunction(key string, value func(args ...interface{}) (interface{}, error)) error {
2021-07-20 23:27:12 -07:00
if _, ok := functions[key]; !ok {
functions[key] = value
return nil
2021-07-20 23:27:12 -07:00
}
return errors.New("duplicate helper function key defined")
2021-07-20 23:27:12 -07:00
}
2020-12-22 03:54:55 +05:30
func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func trimAll(s, cutset string) string {
for _, c := range cutset {
s = strings.ReplaceAll(s, string(c), "")
}
return s
}
func randSeq(base string, n int) string {
b := make([]rune, n)
for i := range b {
b[i] = rune(base[rand.Intn(len(base))])
}
return string(b)
}