mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-08 03:00:27 +08:00
WAF操作符增加“包含SQL注入-严格模式”
This commit is contained in:
@@ -16,11 +16,12 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DetectSQLInjectionCache detect sql injection in string with cache
|
// DetectSQLInjectionCache detect sql injection in string with cache
|
||||||
func DetectSQLInjectionCache(input string, cacheLife utils.CacheLife) bool {
|
func DetectSQLInjectionCache(input string, isStrict bool, cacheLife utils.CacheLife) bool {
|
||||||
var l = len(input)
|
var l = len(input)
|
||||||
|
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
@@ -28,7 +29,7 @@ func DetectSQLInjectionCache(input string, cacheLife utils.CacheLife) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cacheLife <= 0 || l < 128 || l > utils.MaxCacheDataSize {
|
if cacheLife <= 0 || l < 128 || l > utils.MaxCacheDataSize {
|
||||||
return DetectSQLInjection(input)
|
return DetectSQLInjection(input, isStrict)
|
||||||
}
|
}
|
||||||
|
|
||||||
var hash = xxhash.Sum64String(input)
|
var hash = xxhash.Sum64String(input)
|
||||||
@@ -38,7 +39,7 @@ func DetectSQLInjectionCache(input string, cacheLife utils.CacheLife) bool {
|
|||||||
return item.Value == 1
|
return item.Value == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = DetectSQLInjection(input)
|
var result = DetectSQLInjection(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 {
|
||||||
@@ -48,11 +49,23 @@ func DetectSQLInjectionCache(input string, cacheLife utils.CacheLife) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DetectSQLInjection detect sql injection in string
|
// DetectSQLInjection detect sql injection in string
|
||||||
func DetectSQLInjection(input string) bool {
|
func DetectSQLInjection(input string, isStrict bool) bool {
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isStrict {
|
||||||
|
if len(input) > 1024 {
|
||||||
|
if !utf8.ValidString(input[:1024]) && !utf8.ValidString(input[:1023]) && !utf8.ValidString(input[:1022]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !utf8.ValidString(input) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if detectSQLInjectionOne(input) {
|
if detectSQLInjectionOne(input) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,21 +15,23 @@ import (
|
|||||||
|
|
||||||
func TestDetectSQLInjection(t *testing.T) {
|
func TestDetectSQLInjection(t *testing.T) {
|
||||||
var a = assert.NewAssertion(t)
|
var a = assert.NewAssertion(t)
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("' UNION SELECT * FROM myTable"))
|
for _, isStrict := range []bool{true, false} {
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("id=1 ' UNION select * from a"))
|
a.IsTrue(injectionutils.DetectSQLInjection("' UNION SELECT * FROM myTable", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("asdf asd ; -1' and 1=1 union/* foo */select load_file('/etc/passwd')--"))
|
a.IsTrue(injectionutils.DetectSQLInjection("id=1 ' UNION select * from a", isStrict))
|
||||||
a.IsFalse(injectionutils.DetectSQLInjection("' UNION SELECT1 * FROM myTable"))
|
a.IsTrue(injectionutils.DetectSQLInjection("asdf asd ; -1' and 1=1 union/* foo */select load_file('/etc/passwd')--", isStrict))
|
||||||
a.IsFalse(injectionutils.DetectSQLInjection("1234"))
|
a.IsFalse(injectionutils.DetectSQLInjection("' UNION SELECT1 * FROM myTable", isStrict))
|
||||||
a.IsFalse(injectionutils.DetectSQLInjection(""))
|
a.IsFalse(injectionutils.DetectSQLInjection("1234", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("id=123 OR 1=1&b=2"))
|
a.IsFalse(injectionutils.DetectSQLInjection("", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("id=123&b=456&c=1' or 2=2"))
|
a.IsTrue(injectionutils.DetectSQLInjection("id=123 OR 1=1&b=2", isStrict))
|
||||||
a.IsFalse(injectionutils.DetectSQLInjection("?"))
|
a.IsTrue(injectionutils.DetectSQLInjection("id=123&b=456&c=1' or 2=2", isStrict))
|
||||||
a.IsFalse(injectionutils.DetectSQLInjection("/hello?age=22"))
|
a.IsFalse(injectionutils.DetectSQLInjection("?", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("/sql/injection?id=123 or 1=1"))
|
a.IsFalse(injectionutils.DetectSQLInjection("/hello?age=22", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("/sql/injection?id=123%20or%201=1"))
|
a.IsTrue(injectionutils.DetectSQLInjection("/sql/injection?id=123 or 1=1", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("https://example.com/sql/injection?id=123%20or%201=1"))
|
a.IsTrue(injectionutils.DetectSQLInjection("/sql/injection?id=123%20or%201=1", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("id=123%20or%201=1"))
|
a.IsTrue(injectionutils.DetectSQLInjection("https://example.com/sql/injection?id=123%20or%201=1", isStrict))
|
||||||
a.IsTrue(injectionutils.DetectSQLInjection("https://example.com/' or 1=1"))
|
a.IsTrue(injectionutils.DetectSQLInjection("id=123%20or%201=1", isStrict))
|
||||||
|
a.IsTrue(injectionutils.DetectSQLInjection("https://example.com/' or 1=1", isStrict))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDetectSQLInjection(b *testing.B) {
|
func BenchmarkDetectSQLInjection(b *testing.B) {
|
||||||
@@ -37,7 +39,7 @@ func BenchmarkDetectSQLInjection(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjection("asdf asd ; -1' and 1=1 union/* foo */select load_file('/etc/passwd')--")
|
_ = injectionutils.DetectSQLInjection("asdf asd ; -1' and 1=1 union/* foo */select load_file('/etc/passwd')--", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -47,7 +49,7 @@ func BenchmarkDetectSQLInjection_URL(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjection("/sql/injection?id=123 or 1=1")
|
_ = injectionutils.DetectSQLInjection("/sql/injection?id=123 or 1=1", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -57,7 +59,7 @@ func BenchmarkDetectSQLInjection_Normal_Small(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjection("a/sql/injection?id=1234")
|
_ = injectionutils.DetectSQLInjection("a/sql/injection?id=1234", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -67,7 +69,7 @@ func BenchmarkDetectSQLInjection_URL_Normal_Small(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjection("/sql/injection?id=" + types.String(rands.Int64()%10000))
|
_ = injectionutils.DetectSQLInjection("/sql/injection?id="+types.String(rands.Int64()%10000), false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -77,7 +79,7 @@ func BenchmarkDetectSQLInjection_URL_Normal_Middle(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjection("/search?q=libinjection+fingerprint&newwindow=1&sca_esv=589290862&sxsrf=AMwHvKnxuLoejn2XlNniffC12E_xc35M7Q%3A1702090118361&ei=htvzzebfFZfo1e8PvLGggAk&ved=0ahUKEwjTsYmnq4GDAxUWdPOHHbwkCJAQ4ddDCBA&uact=5&oq=libinjection+fingerprint&gs_lp=Egxnd3Mtd2l6LXNlcnAiGIxpYmluamVjdGlvbmBmaW5nKXJwcmludTIEEAAYHjIGVAAYCBgeSiEaUPkRWKFZcAJ4AZABAJgBHgGgAfoEqgwDMC40uAEGyAEA-AEBwgIKEAFYTxjWMuiwA-IDBBgAVteIBgGQBgI&sclient=gws-wiz-serp#ip=1")
|
_ = injectionutils.DetectSQLInjection("/search?q=libinjection+fingerprint&newwindow=1&sca_esv=589290862&sxsrf=AMwHvKnxuLoejn2XlNniffC12E_xc35M7Q%3A1702090118361&ei=htvzzebfFZfo1e8PvLGggAk&ved=0ahUKEwjTsYmnq4GDAxUWdPOHHbwkCJAQ4ddDCBA&uact=5&oq=libinjection+fingerprint&gs_lp=Egxnd3Mtd2l6LXNlcnAiGIxpYmluamVjdGlvbmBmaW5nKXJwcmludTIEEAAYHjIGVAAYCBgeSiEaUPkRWKFZcAJ4AZABAJgBHgGgAfoEqgwDMC40uAEGyAEA-AEBwgIKEAFYTxjWMuiwA-IDBBgAVteIBgGQBgI&sclient=gws-wiz-serp#ip=1", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -87,7 +89,7 @@ func BenchmarkDetectSQLInjection_URL_Normal_Small_Cache(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjectionCache("/sql/injection?id="+types.String(rands.Int64()%10000), utils.CacheMiddleLife)
|
_ = injectionutils.DetectSQLInjectionCache("/sql/injection?id="+types.String(rands.Int64()%10000), false, utils.CacheMiddleLife)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -100,7 +102,7 @@ func BenchmarkDetectSQLInjection_Normal_Large(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjection("a/sql/injection?id=" + types.String(rands.Int64()%10000) + "&s=" + s + "&v=%20")
|
_ = injectionutils.DetectSQLInjection("a/sql/injection?id="+types.String(rands.Int64()%10000)+"&s="+s+"&v=%20", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -112,7 +114,7 @@ func BenchmarkDetectSQLInjection_Normal_Large_Cache(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjectionCache("a/sql/injection?id="+types.String(rands.Int64()%10000)+"&s="+s, utils.CacheMiddleLife)
|
_ = injectionutils.DetectSQLInjectionCache("a/sql/injection?id="+types.String(rands.Int64()%10000)+"&s="+s, false, utils.CacheMiddleLife)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -122,7 +124,7 @@ func BenchmarkDetectSQLInjection_URL_Unescape(b *testing.B) {
|
|||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
_ = injectionutils.DetectSQLInjection("/sql/injection?id=123%20or%201=1")
|
_ = injectionutils.DetectSQLInjection("/sql/injection?id=123%20or%201=1", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -578,27 +578,28 @@ func (this *Rule) Test(value any) bool {
|
|||||||
return runes.ContainsAllWords(this.stringifyValue(value), this.stringValues, this.IsCaseInsensitive)
|
return runes.ContainsAllWords(this.stringifyValue(value), this.stringValues, this.IsCaseInsensitive)
|
||||||
case RuleOperatorNotContainsAnyWord:
|
case RuleOperatorNotContainsAnyWord:
|
||||||
return !runes.ContainsAnyWordRunes(this.stringifyValue(value), this.stringValueRunes, this.IsCaseInsensitive)
|
return !runes.ContainsAnyWordRunes(this.stringifyValue(value), this.stringValueRunes, this.IsCaseInsensitive)
|
||||||
case RuleOperatorContainsSQLInjection:
|
case RuleOperatorContainsSQLInjection, RuleOperatorContainsSQLInjectionStrictly:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
var isStrict = this.Operator == RuleOperatorContainsSQLInjectionStrictly
|
||||||
switch xValue := value.(type) {
|
switch xValue := value.(type) {
|
||||||
case []string:
|
case []string:
|
||||||
for _, v := range xValue {
|
for _, v := range xValue {
|
||||||
if injectionutils.DetectSQLInjectionCache(v, this.cacheLife) {
|
if injectionutils.DetectSQLInjectionCache(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.DetectSQLInjectionCache(string(v), this.cacheLife) {
|
if injectionutils.DetectSQLInjectionCache(string(v), isStrict, this.cacheLife) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
return injectionutils.DetectSQLInjectionCache(this.stringifyValue(value), this.cacheLife)
|
return injectionutils.DetectSQLInjectionCache(this.stringifyValue(value), isStrict, this.cacheLife)
|
||||||
}
|
}
|
||||||
case RuleOperatorContainsXSS, RuleOperatorContainsXSSStrictly:
|
case RuleOperatorContainsXSS, RuleOperatorContainsXSSStrictly:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
|
|||||||
@@ -4,35 +4,36 @@ type RuleOperator = string
|
|||||||
type RuleCaseInsensitive = string
|
type RuleCaseInsensitive = string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RuleOperatorGt RuleOperator = "gt"
|
RuleOperatorGt RuleOperator = "gt"
|
||||||
RuleOperatorGte RuleOperator = "gte"
|
RuleOperatorGte RuleOperator = "gte"
|
||||||
RuleOperatorLt RuleOperator = "lt"
|
RuleOperatorLt RuleOperator = "lt"
|
||||||
RuleOperatorLte RuleOperator = "lte"
|
RuleOperatorLte RuleOperator = "lte"
|
||||||
RuleOperatorEq RuleOperator = "eq"
|
RuleOperatorEq RuleOperator = "eq"
|
||||||
RuleOperatorNeq RuleOperator = "neq"
|
RuleOperatorNeq RuleOperator = "neq"
|
||||||
RuleOperatorEqString RuleOperator = "eq string"
|
RuleOperatorEqString RuleOperator = "eq string"
|
||||||
RuleOperatorNeqString RuleOperator = "neq string"
|
RuleOperatorNeqString RuleOperator = "neq string"
|
||||||
RuleOperatorMatch RuleOperator = "match"
|
RuleOperatorMatch RuleOperator = "match"
|
||||||
RuleOperatorNotMatch RuleOperator = "not match"
|
RuleOperatorNotMatch RuleOperator = "not match"
|
||||||
RuleOperatorWildcardMatch RuleOperator = "wildcard match"
|
RuleOperatorWildcardMatch RuleOperator = "wildcard match"
|
||||||
RuleOperatorWildcardNotMatch RuleOperator = "wildcard not match"
|
RuleOperatorWildcardNotMatch RuleOperator = "wildcard not match"
|
||||||
RuleOperatorContains RuleOperator = "contains"
|
RuleOperatorContains RuleOperator = "contains"
|
||||||
RuleOperatorNotContains RuleOperator = "not contains"
|
RuleOperatorNotContains RuleOperator = "not contains"
|
||||||
RuleOperatorPrefix RuleOperator = "prefix"
|
RuleOperatorPrefix RuleOperator = "prefix"
|
||||||
RuleOperatorSuffix RuleOperator = "suffix"
|
RuleOperatorSuffix RuleOperator = "suffix"
|
||||||
RuleOperatorContainsAny RuleOperator = "contains any"
|
RuleOperatorContainsAny RuleOperator = "contains any"
|
||||||
RuleOperatorContainsAll RuleOperator = "contains all"
|
RuleOperatorContainsAll RuleOperator = "contains all"
|
||||||
RuleOperatorContainsAnyWord RuleOperator = "contains any word"
|
RuleOperatorContainsAnyWord RuleOperator = "contains any word"
|
||||||
RuleOperatorContainsAllWords RuleOperator = "contains all words"
|
RuleOperatorContainsAllWords RuleOperator = "contains all words"
|
||||||
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"
|
RuleOperatorContainsSQLInjectionStrictly RuleOperator = "contains sql injection strictly"
|
||||||
RuleOperatorContainsXSSStrictly RuleOperator = "contains xss strictly"
|
RuleOperatorContainsXSS RuleOperator = "contains xss"
|
||||||
RuleOperatorInIPList RuleOperator = "in ip list"
|
RuleOperatorContainsXSSStrictly RuleOperator = "contains xss strictly"
|
||||||
RuleOperatorHasKey RuleOperator = "has key" // has key in slice or map
|
RuleOperatorInIPList RuleOperator = "in ip list"
|
||||||
RuleOperatorVersionGt RuleOperator = "version gt"
|
RuleOperatorHasKey RuleOperator = "has key" // has key in slice or map
|
||||||
RuleOperatorVersionLt RuleOperator = "version lt"
|
RuleOperatorVersionGt RuleOperator = "version gt"
|
||||||
RuleOperatorVersionRange RuleOperator = "version range"
|
RuleOperatorVersionLt RuleOperator = "version lt"
|
||||||
|
RuleOperatorVersionRange RuleOperator = "version range"
|
||||||
|
|
||||||
RuleOperatorContainsBinary RuleOperator = "contains binary" // contains binary
|
RuleOperatorContainsBinary RuleOperator = "contains binary" // contains binary
|
||||||
RuleOperatorNotContainsBinary RuleOperator = "not contains binary" // not contains binary
|
RuleOperatorNotContainsBinary RuleOperator = "not contains binary" // not contains binary
|
||||||
|
|||||||
Reference in New Issue
Block a user