github.com/TeaOSLab/EdgeNode@v1.3.8/internal/waf/injectionutils/utils_xss.go (about) 1 // Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . 2 3 package injectionutils 4 5 /* 6 #cgo CFLAGS: -O2 -I./libinjection/src 7 8 #include <libinjection.h> 9 #include <stdlib.h> 10 */ 11 import "C" 12 import ( 13 "github.com/TeaOSLab/EdgeNode/internal/utils/fasttime" 14 "github.com/TeaOSLab/EdgeNode/internal/waf/utils" 15 "github.com/cespare/xxhash/v2" 16 "net/url" 17 "strconv" 18 "strings" 19 "unsafe" 20 ) 21 22 func DetectXSSCache(input string, isStrict bool, cacheLife utils.CacheLife) bool { 23 var l = len(input) 24 25 if l == 0 { 26 return false 27 } 28 29 if cacheLife <= 0 || l < 512 || l > utils.MaxCacheDataSize { 30 return DetectXSS(input, isStrict) 31 } 32 33 var hash = xxhash.Sum64String(input) 34 var key = "WAF@XSS@" + strconv.FormatUint(hash, 10) 35 if isStrict { 36 key += "@1" 37 } 38 var item = utils.SharedCache.Read(key) 39 if item != nil { 40 return item.Value == 1 41 } 42 43 var result = DetectXSS(input, isStrict) 44 if result { 45 utils.SharedCache.Write(key, 1, fasttime.Now().Unix()+cacheLife) 46 } else { 47 utils.SharedCache.Write(key, 0, fasttime.Now().Unix()+cacheLife) 48 } 49 return result 50 } 51 52 // DetectXSS detect XSS in string 53 func DetectXSS(input string, isStrict bool) bool { 54 if len(input) == 0 { 55 return false 56 } 57 58 if detectXSSOne(input, isStrict) { 59 return true 60 } 61 62 // 兼容 /PATH?URI 63 if (input[0] == '/' || strings.HasPrefix(input, "http://") || strings.HasPrefix(input, "https://")) && len(input) < 1024 { 64 var argsIndex = strings.Index(input, "?") 65 if argsIndex > 0 { 66 var args = input[argsIndex+1:] 67 unescapeArgs, err := url.QueryUnescape(args) 68 if err == nil && args != unescapeArgs { 69 return detectXSSOne(args, isStrict) || detectXSSOne(unescapeArgs, isStrict) 70 } else { 71 return detectXSSOne(args, isStrict) 72 } 73 } 74 } else { 75 unescapedInput, err := url.QueryUnescape(input) 76 if err == nil && input != unescapedInput { 77 return detectXSSOne(unescapedInput, isStrict) 78 } 79 } 80 81 return false 82 } 83 84 func detectXSSOne(input string, isStrict bool) bool { 85 if len(input) == 0 { 86 return false 87 } 88 89 var cInput = C.CString(input) 90 defer C.free(unsafe.Pointer(cInput)) 91 92 var isStrictInt = 0 93 if isStrict { 94 isStrictInt = 1 95 } 96 return C.libinjection_xss(cInput, C.size_t(len(input)), C.int(isStrictInt)) == 1 97 }