284 lines
7.8 KiB
Go
Raw Normal View History

2020-12-22 03:54:55 +05:30
package dsl
import (
2020-12-22 03:54:55 +05:30
"bytes"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
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"
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) {
2020-12-24 12:13:18 +05:30
return strings.Trim(types.ToString(args[0]), types.ToString(args[2])), 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])))
2020-10-16 13:27:02 +02:00
return 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) {
2020-12-24 12:13:18 +05:30
return url.PathEscape(types.ToString(args[0])), nil
2021-07-20 23:27:12 -07:00
},
"url_decode": func(args ...interface{}) (interface{}, error) {
2020-12-24 12:13:18 +05:30
return url.PathUnescape(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()
2020-12-24 12:13:18 +05:30
_, err := h.Write([]byte(types.ToString(args[0])))
if 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()
2020-12-24 12:13:18 +05:30
_, err := h.Write([]byte(types.ToString(args[0])))
if 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 {
l = args[0].(int)
}
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 {
l = args[0].(int)
}
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 {
l = args[0].(int)
}
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 {
l = args[0].(int)
}
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 = args[0].(int)
}
2020-10-16 22:07:00 +02:00
if len(args) >= withMaxRandArgsSize {
2020-10-11 20:26:27 +02:00
max = args[1].(int)
}
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
},
}
// HelperFunctions contains the dsl helper functions
func HelperFunctions() map[string]govaluate.ExpressionFunction {
return functions
}
2020-12-22 03:54:55 +05:30
2021-07-20 23:27:12 -07:00
func AddHelperFunction(key string, value func(args ...interface{}) (interface{}, error)) {
if _, ok := functions[key]; !ok {
functions[key] = value
}
}
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)
}
func insertInto(s string, interval int, sep rune) string {
var buffer bytes.Buffer
before := interval - 1
last := len(s) - 1
for i, char := range s {
buffer.WriteRune(char)
if i%interval == before && i != last {
buffer.WriteRune(sep)
}
}
buffer.WriteRune(sep)
return buffer.String()
}