From a17878f5b2d2567d7739da705b1a03d12bf49e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=A5=E8=B6=85?= Date: Fri, 6 Jan 2023 20:07:15 +0800 Subject: [PATCH] =?UTF-8?q?WAF=E5=A2=9E=E5=8A=A0=E5=8C=85=E5=90=AB?= =?UTF-8?q?=E4=BB=BB=E4=B8=80=E5=AD=97=E7=AC=A6=E4=B8=B2=E3=80=81=E5=8C=85?= =?UTF-8?q?=E5=90=AB=E6=89=80=E6=9C=89=E5=AD=97=E7=AC=A6=E4=B8=B2=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/waf/rule.go | 45 +++++++++++++++++++++++-- internal/waf/rule_operator.go | 2 ++ internal/waf/values/ip_list.go | 2 +- internal/waf/values/string_list.go | 18 +++++++--- internal/waf/values/string_list_test.go | 17 ++++++++-- 5 files changed, 74 insertions(+), 10 deletions(-) diff --git a/internal/waf/rule.go b/internal/waf/rule.go index 46a71a8..de3a60b 100644 --- a/internal/waf/rule.go +++ b/internal/waf/rule.go @@ -49,8 +49,7 @@ type Rule struct { ipValue net.IP ipRangeListValue *values.IPRangeList - numberListValue *values.NumberList - stringListValue *values.StringList + stringValues []string floatValue float64 reg *re.Regexp @@ -75,6 +74,21 @@ func (this *Rule) Init() error { this.floatValue = types.Float64(this.Value) case RuleOperatorNeq: this.floatValue = types.Float64(this.Value) + case RuleOperatorContainsAny, RuleOperatorContainsAll: + this.stringValues = []string{} + if len(this.Value) > 0 { + var lines = strings.Split(this.Value, "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if len(line) > 0 { + if this.IsCaseInsensitive { + this.stringValues = append(this.stringValues, strings.ToLower(line)) + } else { + this.stringValues = append(this.stringValues, line) + } + } + } + } case RuleOperatorMatch: v := this.Value if this.IsCaseInsensitive && !strings.HasPrefix(v, "(?i)") { @@ -452,6 +466,33 @@ func (this *Rule) Test(value interface{}) bool { } else { return strings.HasSuffix(types.String(value), this.Value) } + case RuleOperatorContainsAny: + var stringValue = types.String(value) + if this.IsCaseInsensitive { + stringValue = strings.ToLower(stringValue) + } + if len(stringValue) > 0 && len(this.stringValues) > 0 { + for _, v := range this.stringValues { + if strings.Contains(stringValue, v) { + return true + } + } + } + return false + case RuleOperatorContainsAll: + var stringValue = types.String(value) + if this.IsCaseInsensitive { + stringValue = strings.ToLower(stringValue) + } + if len(stringValue) > 0 && len(this.stringValues) > 0 { + for _, v := range this.stringValues { + if !strings.Contains(stringValue, v) { + return false + } + } + return true + } + return false case RuleOperatorContainsBinary: data, _ := base64.StdEncoding.DecodeString(types.String(this.Value)) if this.IsCaseInsensitive { diff --git a/internal/waf/rule_operator.go b/internal/waf/rule_operator.go index 879f8db..2576541 100644 --- a/internal/waf/rule_operator.go +++ b/internal/waf/rule_operator.go @@ -18,6 +18,8 @@ const ( RuleOperatorNotContains RuleOperator = "not contains" RuleOperatorPrefix RuleOperator = "prefix" RuleOperatorSuffix RuleOperator = "suffix" + RuleOperatorContainsAny RuleOperator = "containsAny" + RuleOperatorContainsAll RuleOperator = "containsAll" RuleOperatorHasKey RuleOperator = "has key" // has key in slice or map RuleOperatorVersionGt RuleOperator = "version gt" RuleOperatorVersionLt RuleOperator = "version lt" diff --git a/internal/waf/values/ip_list.go b/internal/waf/values/ip_list.go index 8d717bc..16148fb 100644 --- a/internal/waf/values/ip_list.go +++ b/internal/waf/values/ip_list.go @@ -3,5 +3,5 @@ package values func ParseIPList(v string) *StringList { - return ParseStringList(v) + return ParseStringList(v, false) } diff --git a/internal/waf/values/string_list.go b/internal/waf/values/string_list.go index 76c2e68..a42dcd0 100644 --- a/internal/waf/values/string_list.go +++ b/internal/waf/values/string_list.go @@ -8,17 +8,19 @@ import ( ) type StringList struct { - ValueMap map[string]zero.Zero + ValueMap map[string]zero.Zero + CaseInsensitive bool } -func NewStringList() *StringList { +func NewStringList(caseInsensitive bool) *StringList { return &StringList{ - ValueMap: map[string]zero.Zero{}, + ValueMap: map[string]zero.Zero{}, + CaseInsensitive: caseInsensitive, } } -func ParseStringList(v string) *StringList { - var list = NewStringList() +func ParseStringList(v string, caseInsensitive bool) *StringList { + var list = NewStringList(caseInsensitive) if len(v) == 0 { return list } @@ -34,6 +36,9 @@ func ParseStringList(v string) *StringList { for _, value := range values { value = strings.TrimSpace(value) if len(value) > 0 { + if caseInsensitive { + value = strings.ToLower(value) + } list.ValueMap[value] = zero.Zero{} } } @@ -42,6 +47,9 @@ func ParseStringList(v string) *StringList { } func (this *StringList) Contains(f string) bool { + if this.CaseInsensitive { + f = strings.ToLower(f) + } _, ok := this.ValueMap[f] return ok } diff --git a/internal/waf/values/string_list_test.go b/internal/waf/values/string_list_test.go index 225c5be..81de697 100644 --- a/internal/waf/values/string_list_test.go +++ b/internal/waf/values/string_list_test.go @@ -12,7 +12,7 @@ func TestParseStringList(t *testing.T) { var a = assert.NewAssertion(t) { - var list = values.ParseStringList("") + var list = values.ParseStringList("", false) a.IsFalse(list.Contains("hello")) } @@ -22,9 +22,22 @@ func TestParseStringList(t *testing.T) { world hi -people`) +people`, false) a.IsTrue(list.Contains("hello")) a.IsFalse(list.Contains("hello1")) + a.IsFalse(list.Contains("Hello")) a.IsTrue(list.Contains("hi")) } + { + var list = values.ParseStringList(`Hello + +world +hi + +people`, true) + a.IsTrue(list.Contains("hello")) + a.IsTrue(list.Contains("Hello")) + a.IsTrue(list.Contains("HELLO")) + a.IsFalse(list.Contains("How")) + } }