mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-07 18:50:27 +08:00
WAF操作符增加“包含XSS注入-严格模式”
This commit is contained in:
@@ -58,7 +58,7 @@ int libinjection_sqli(const char* s, size_t slen, char fingerprint[]);
|
|||||||
* \return 1 if XSS found, 0 if benign
|
* \return 1 if XSS found, 0 if benign
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int libinjection_xss(const char* s, size_t slen);
|
int libinjection_xss(const char* s, size_t slen, int strictMode);
|
||||||
|
|
||||||
LIBINJECTION_END_DECLS
|
LIBINJECTION_END_DECLS
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ typedef enum attribute {
|
|||||||
|
|
||||||
|
|
||||||
static attribute_t is_black_attr(const char* s, size_t len);
|
static attribute_t is_black_attr(const char* s, size_t len);
|
||||||
static int is_black_tag(const char* s, size_t len);
|
static int is_black_tag(const char* s, size_t len, int strictMode);
|
||||||
static int is_black_url(const char* s, size_t len);
|
static int is_black_url(const char* s, size_t len);
|
||||||
static int cstrcasecmp_with_null(const char *a, const char *b, size_t n);
|
static int cstrcasecmp_with_null(const char *a, const char *b, size_t n);
|
||||||
static int html_decode_char_at(const char* src, size_t len, size_t* consumed);
|
static int html_decode_char_at(const char* src, size_t len, size_t* consumed);
|
||||||
@@ -492,6 +492,35 @@ static stringtype_t BLACKATTR[] = {
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// GoEdge: change BLACKTAG to STRICT_BLACKTAG
|
||||||
|
static const char* STRICT_BLACKTAG[] = {
|
||||||
|
"APPLET"
|
||||||
|
, "AUDIO"
|
||||||
|
, "BASE"
|
||||||
|
, "COMMENT" /* IE http://html5sec.org/#38 */
|
||||||
|
, "EMBED"
|
||||||
|
, "FORM"
|
||||||
|
, "FRAME"
|
||||||
|
, "FRAMESET"
|
||||||
|
, "HANDLER" /* Opera SVG, effectively a script tag */
|
||||||
|
, "IFRAME"
|
||||||
|
, "IMPORT"
|
||||||
|
, "ISINDEX"
|
||||||
|
, "LINK"
|
||||||
|
, "LISTENER"
|
||||||
|
/* , "MARQUEE" */
|
||||||
|
, "META"
|
||||||
|
, "NOSCRIPT"
|
||||||
|
, "OBJECT"
|
||||||
|
, "SCRIPT"
|
||||||
|
, "STYLE"
|
||||||
|
, "VIDEO"
|
||||||
|
, "VMLFRAME"
|
||||||
|
, "XML"
|
||||||
|
, "XSS"
|
||||||
|
, NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const char* BLACKTAG[] = {
|
static const char* BLACKTAG[] = {
|
||||||
"APPLET"
|
"APPLET"
|
||||||
/* , "AUDIO" */
|
/* , "AUDIO" */
|
||||||
@@ -515,7 +544,6 @@ static const char* BLACKTAG[] = {
|
|||||||
, "STYLE"
|
, "STYLE"
|
||||||
/* , "VIDEO" */
|
/* , "VIDEO" */
|
||||||
, "VMLFRAME"
|
, "VMLFRAME"
|
||||||
, "XML"
|
|
||||||
, "XSS"
|
, "XSS"
|
||||||
, NULL
|
, NULL
|
||||||
};
|
};
|
||||||
@@ -606,7 +634,7 @@ static int htmlencode_startswith(const char *a, const char *b, size_t n)
|
|||||||
return (*a == 0) ? 1 : 0;
|
return (*a == 0) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_black_tag(const char* s, size_t len)
|
static int is_black_tag(const char* s, size_t len, int strictMode)
|
||||||
{
|
{
|
||||||
const char** black;
|
const char** black;
|
||||||
|
|
||||||
@@ -614,7 +642,11 @@ static int is_black_tag(const char* s, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strictMode == 1) {
|
||||||
|
black = STRICT_BLACKTAG;
|
||||||
|
} else {
|
||||||
black = BLACKTAG;
|
black = BLACKTAG;
|
||||||
|
}
|
||||||
while (*black != NULL) {
|
while (*black != NULL) {
|
||||||
if (cstrcasecmp_with_null(*black, s, len) == 0) {
|
if (cstrcasecmp_with_null(*black, s, len) == 0) {
|
||||||
/* printf("Got black tag %s\n", *black); */
|
/* printf("Got black tag %s\n", *black); */
|
||||||
@@ -729,7 +761,7 @@ static int is_black_url(const char* s, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libinjection_is_xss(const char* s, size_t len, int flags)
|
int libinjection_is_xss(const char* s, size_t len, int flags, int strictMode)
|
||||||
{
|
{
|
||||||
h5_state_t h5;
|
h5_state_t h5;
|
||||||
attribute_t attr = TYPE_NONE;
|
attribute_t attr = TYPE_NONE;
|
||||||
@@ -743,7 +775,7 @@ int libinjection_is_xss(const char* s, size_t len, int flags)
|
|||||||
if (h5.token_type == DOCTYPE) {
|
if (h5.token_type == DOCTYPE) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (h5.token_type == TAG_NAME_OPEN) {
|
} else if (h5.token_type == TAG_NAME_OPEN) {
|
||||||
if (is_black_tag(h5.token_start, h5.token_len)) {
|
if (is_black_tag(h5.token_start, h5.token_len, strictMode)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (h5.token_type == ATTR_NAME) {
|
} else if (h5.token_type == ATTR_NAME) {
|
||||||
@@ -835,21 +867,21 @@ int libinjection_is_xss(const char* s, size_t len, int flags)
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int libinjection_xss(const char* s, size_t slen)
|
int libinjection_xss(const char* s, size_t slen, int strictMode)
|
||||||
{
|
{
|
||||||
if (libinjection_is_xss(s, slen, DATA_STATE)) {
|
if (libinjection_is_xss(s, slen, DATA_STATE, strictMode)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (libinjection_is_xss(s, slen, VALUE_NO_QUOTE)) {
|
if (libinjection_is_xss(s, slen, VALUE_NO_QUOTE, strictMode)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (libinjection_is_xss(s, slen, VALUE_SINGLE_QUOTE)) {
|
if (libinjection_is_xss(s, slen, VALUE_SINGLE_QUOTE, strictMode)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (libinjection_is_xss(s, slen, VALUE_DOUBLE_QUOTE)) {
|
if (libinjection_is_xss(s, slen, VALUE_DOUBLE_QUOTE, strictMode)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (libinjection_is_xss(s, slen, VALUE_BACK_QUOTE)) {
|
if (libinjection_is_xss(s, slen, VALUE_BACK_QUOTE, strictMode)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int libinjection_is_xss(const char* s, size_t len, int flags);
|
int libinjection_is_xss(const char* s, size_t len, int flags, int strictMode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
#include "libinjection/src/libinjection_xss.c"
|
#include "libinjection/src/libinjection_xss.c"
|
||||||
#include "libinjection/src/libinjection_html5.c"
|
#include "libinjection/src/libinjection_html5.c"
|
||||||
|
|
||||||
#define GOEDGE_VERSION "23" // last version is for GoEdge change
|
#define GOEDGE_VERSION "24" // last version is for GoEdge change
|
||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DetectXSSCache(input string, cacheLife utils.CacheLife) bool {
|
func DetectXSSCache(input string, isStrict bool, cacheLife utils.CacheLife) bool {
|
||||||
var l = len(input)
|
var l = len(input)
|
||||||
|
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
@@ -27,17 +27,20 @@ func DetectXSSCache(input string, cacheLife utils.CacheLife) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cacheLife <= 0 || l < 512 || l > utils.MaxCacheDataSize {
|
if cacheLife <= 0 || l < 512 || l > utils.MaxCacheDataSize {
|
||||||
return DetectXSS(input)
|
return DetectXSS(input, isStrict)
|
||||||
}
|
}
|
||||||
|
|
||||||
var hash = xxhash.Sum64String(input)
|
var hash = xxhash.Sum64String(input)
|
||||||
var key = "WAF@XSS@" + strconv.FormatUint(hash, 10)
|
var key = "WAF@XSS@" + strconv.FormatUint(hash, 10)
|
||||||
|
if isStrict {
|
||||||
|
key += "@1"
|
||||||
|
}
|
||||||
var item = utils.SharedCache.Read(key)
|
var item = utils.SharedCache.Read(key)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
return item.Value == 1
|
return item.Value == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = DetectXSS(input)
|
var result = DetectXSS(input, isStrict)
|
||||||
if result {
|
if result {
|
||||||
utils.SharedCache.Write(key, 1, fasttime.Now().Unix()+cacheLife)
|
utils.SharedCache.Write(key, 1, fasttime.Now().Unix()+cacheLife)
|
||||||
} else {
|
} else {
|
||||||
@@ -47,12 +50,12 @@ func DetectXSSCache(input string, cacheLife utils.CacheLife) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DetectXSS detect XSS in string
|
// DetectXSS detect XSS in string
|
||||||
func DetectXSS(input string) bool {
|
func DetectXSS(input string, isStrict bool) bool {
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if detectXSSOne(input) {
|
if detectXSSOne(input, isStrict) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,22 +66,22 @@ func DetectXSS(input string) bool {
|
|||||||
var args = input[argsIndex+1:]
|
var args = input[argsIndex+1:]
|
||||||
unescapeArgs, err := url.QueryUnescape(args)
|
unescapeArgs, err := url.QueryUnescape(args)
|
||||||
if err == nil && args != unescapeArgs {
|
if err == nil && args != unescapeArgs {
|
||||||
return detectXSSOne(args) || detectXSSOne(unescapeArgs)
|
return detectXSSOne(args, isStrict) || detectXSSOne(unescapeArgs, isStrict)
|
||||||
} else {
|
} else {
|
||||||
return detectXSSOne(args)
|
return detectXSSOne(args, isStrict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unescapedInput, err := url.QueryUnescape(input)
|
unescapedInput, err := url.QueryUnescape(input)
|
||||||
if err == nil && input != unescapedInput {
|
if err == nil && input != unescapedInput {
|
||||||
return detectXSSOne(unescapedInput)
|
return detectXSSOne(unescapedInput, isStrict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func detectXSSOne(input string) bool {
|
func detectXSSOne(input string, isStrict bool) bool {
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -86,5 +89,9 @@ func detectXSSOne(input string) bool {
|
|||||||
var cInput = C.CString(input)
|
var cInput = C.CString(input)
|
||||||
defer C.free(unsafe.Pointer(cInput))
|
defer C.free(unsafe.Pointer(cInput))
|
||||||
|
|
||||||
return C.libinjection_xss(cInput, C.size_t(len(input))) == 1
|
var isStrictInt = 0
|
||||||
|
if isStrict {
|
||||||
|
isStrictInt = 1
|
||||||
|
}
|
||||||
|
return C.libinjection_xss(cInput, C.size_t(len(input)), C.int(isStrictInt)) == 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,18 +12,18 @@ import (
|
|||||||
|
|
||||||
func TestDetectXSS(t *testing.T) {
|
func TestDetectXSS(t *testing.T) {
|
||||||
var a = assert.NewAssertion(t)
|
var a = assert.NewAssertion(t)
|
||||||
a.IsFalse(injectionutils.DetectXSS(""))
|
a.IsFalse(injectionutils.DetectXSS("", true))
|
||||||
a.IsFalse(injectionutils.DetectXSS("abc"))
|
a.IsFalse(injectionutils.DetectXSS("abc", true))
|
||||||
a.IsTrue(injectionutils.DetectXSS("<script>"))
|
a.IsTrue(injectionutils.DetectXSS("<script>", true))
|
||||||
a.IsTrue(injectionutils.DetectXSS("<link>"))
|
a.IsTrue(injectionutils.DetectXSS("<link>", true))
|
||||||
a.IsFalse(injectionutils.DetectXSS("<html><span>"))
|
a.IsFalse(injectionutils.DetectXSS("<html><span>", true))
|
||||||
a.IsFalse(injectionutils.DetectXSS("<script>"))
|
a.IsFalse(injectionutils.DetectXSS("<script>", true))
|
||||||
a.IsTrue(injectionutils.DetectXSS("/path?onmousedown=a"))
|
a.IsTrue(injectionutils.DetectXSS("/path?onmousedown=a", true))
|
||||||
a.IsTrue(injectionutils.DetectXSS("/path?onkeyup=a"))
|
a.IsTrue(injectionutils.DetectXSS("/path?onkeyup=a", true))
|
||||||
a.IsTrue(injectionutils.DetectXSS("onkeyup=a"))
|
a.IsTrue(injectionutils.DetectXSS("onkeyup=a", true))
|
||||||
a.IsTrue(injectionutils.DetectXSS("<iframe scrolling='no'>"))
|
a.IsTrue(injectionutils.DetectXSS("<iframe scrolling='no'>", true))
|
||||||
a.IsFalse(injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>"))
|
a.IsFalse(injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>", true))
|
||||||
a.IsTrue(injectionutils.DetectXSS("name=s&description=%3Cscript+src%3D%22a.js%22%3Edddd%3C%2Fscript%3E"))
|
a.IsTrue(injectionutils.DetectXSS("name=s&description=%3Cscript+src%3D%22a.js%22%3Edddd%3C%2Fscript%3E", true))
|
||||||
a.IsFalse(injectionutils.DetectXSS(`<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
|
a.IsFalse(injectionutils.DetectXSS(`<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
|
||||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
@@ -31,11 +31,21 @@ func TestDetectXSS(t *testing.T) {
|
|||||||
<tiff:Orientation>1</tiff:Orientation>
|
<tiff:Orientation>1</tiff:Orientation>
|
||||||
</rdf:Description>
|
</rdf:Description>
|
||||||
</rdf:RDF>
|
</rdf:RDF>
|
||||||
</x:xmpmeta>`)) // included in some photo files
|
</x:xmpmeta>`, true)) // included in some photo files
|
||||||
|
a.IsFalse(injectionutils.DetectXSS(`<xml>
|
||||||
|
|
||||||
|
</xml>`, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetectXSS_Strict(t *testing.T) {
|
||||||
|
var a = assert.NewAssertion(t)
|
||||||
|
a.IsFalse(injectionutils.DetectXSS(`<xml>
|
||||||
|
|
||||||
|
</xml>`, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDetectXSS_MISS(b *testing.B) {
|
func BenchmarkDetectXSS_MISS(b *testing.B) {
|
||||||
var result = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>")
|
var result = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>", false)
|
||||||
if result {
|
if result {
|
||||||
b.Fatal("'result' should not be 'true'")
|
b.Fatal("'result' should not be 'true'")
|
||||||
}
|
}
|
||||||
@@ -44,13 +54,13 @@ func BenchmarkDetectXSS_MISS(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>")
|
_ = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDetectXSS_MISS_Cache(b *testing.B) {
|
func BenchmarkDetectXSS_MISS_Cache(b *testing.B) {
|
||||||
var result = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>")
|
var result = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>", false)
|
||||||
if result {
|
if result {
|
||||||
b.Fatal("'result' should not be 'true'")
|
b.Fatal("'result' should not be 'true'")
|
||||||
}
|
}
|
||||||
@@ -59,13 +69,13 @@ func BenchmarkDetectXSS_MISS_Cache(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectXSSCache("<html><body><span>RequestId: 1234567890</span></body></html>", utils.CacheMiddleLife)
|
_ = injectionutils.DetectXSSCache("<html><body><span>RequestId: 1234567890</span></body></html>", false, utils.CacheMiddleLife)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDetectXSS_HIT(b *testing.B) {
|
func BenchmarkDetectXSS_HIT(b *testing.B) {
|
||||||
var result = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span><script src=\"\"></script></body></html>")
|
var result = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span><script src=\"\"></script></body></html>", false)
|
||||||
if !result {
|
if !result {
|
||||||
b.Fatal("'result' should not be 'false'")
|
b.Fatal("'result' should not be 'false'")
|
||||||
}
|
}
|
||||||
@@ -74,7 +84,7 @@ func BenchmarkDetectXSS_HIT(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span><script src=\"\"></script></body></html>")
|
_ = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span><script src=\"\"></script></body></html>", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -600,27 +600,28 @@ func (this *Rule) Test(value any) bool {
|
|||||||
default:
|
default:
|
||||||
return injectionutils.DetectSQLInjectionCache(this.stringifyValue(value), this.cacheLife)
|
return injectionutils.DetectSQLInjectionCache(this.stringifyValue(value), this.cacheLife)
|
||||||
}
|
}
|
||||||
case RuleOperatorContainsXSS:
|
case RuleOperatorContainsXSS, RuleOperatorContainsXSSStrictly:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
var isStrict = this.Operator == RuleOperatorContainsXSSStrictly
|
||||||
switch xValue := value.(type) {
|
switch xValue := value.(type) {
|
||||||
case []string:
|
case []string:
|
||||||
for _, v := range xValue {
|
for _, v := range xValue {
|
||||||
if injectionutils.DetectXSSCache(v, this.cacheLife) {
|
if injectionutils.DetectXSSCache(v, isStrict, this.cacheLife) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
case [][]byte:
|
case [][]byte:
|
||||||
for _, v := range xValue {
|
for _, v := range xValue {
|
||||||
if injectionutils.DetectXSSCache(string(v), this.cacheLife) {
|
if injectionutils.DetectXSSCache(string(v), isStrict, this.cacheLife) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
return injectionutils.DetectXSSCache(this.stringifyValue(value), this.cacheLife)
|
return injectionutils.DetectXSSCache(this.stringifyValue(value), isStrict, this.cacheLife)
|
||||||
}
|
}
|
||||||
case RuleOperatorContainsBinary:
|
case RuleOperatorContainsBinary:
|
||||||
data, _ := base64.StdEncoding.DecodeString(this.stringifyValue(this.Value))
|
data, _ := base64.StdEncoding.DecodeString(this.stringifyValue(this.Value))
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const (
|
|||||||
RuleOperatorNotContainsAnyWord RuleOperator = "not contains any word"
|
RuleOperatorNotContainsAnyWord RuleOperator = "not contains any word"
|
||||||
RuleOperatorContainsSQLInjection RuleOperator = "contains sql injection"
|
RuleOperatorContainsSQLInjection RuleOperator = "contains sql injection"
|
||||||
RuleOperatorContainsXSS RuleOperator = "contains xss"
|
RuleOperatorContainsXSS RuleOperator = "contains xss"
|
||||||
|
RuleOperatorContainsXSSStrictly RuleOperator = "contains xss strictly"
|
||||||
RuleOperatorInIPList RuleOperator = "in ip list"
|
RuleOperatorInIPList RuleOperator = "in ip list"
|
||||||
RuleOperatorHasKey RuleOperator = "has key" // has key in slice or map
|
RuleOperatorHasKey RuleOperator = "has key" // has key in slice or map
|
||||||
RuleOperatorVersionGt RuleOperator = "version gt"
|
RuleOperatorVersionGt RuleOperator = "version gt"
|
||||||
|
|||||||
Reference in New Issue
Block a user