WAF增加“包含XSS注入”操作符

This commit is contained in:
GoEdgeLab
2023-12-08 10:15:18 +08:00
parent 63a1af9f74
commit a070c375e5
7 changed files with 131 additions and 2 deletions

View File

@@ -0,0 +1,4 @@
#define LIBINJECTION_VERSION "3.9.1"
#include "libinjection/src/libinjection_xss.c"
#include "libinjection/src/libinjection_html5.c"

View File

@@ -6,7 +6,6 @@ package injectionutils
#cgo CFLAGS: -I./libinjection/src
#include <libinjection.h>
#include <libinjection_sqli.h>
#include <stdlib.h>
*/
import "C"
@@ -27,7 +26,7 @@ func DetectSQLInjection(input string) bool {
}
// 兼容 /PATH?URI
if input[0] == '/' || strings.HasPrefix(input, "http://") || strings.HasPrefix(input, "https://") {
if (input[0] == '/' || strings.HasPrefix(input, "http://") || strings.HasPrefix(input, "https://")) && len(input) < 4096 {
var argsIndex = strings.Index(input, "?")
if argsIndex > 0 {
var args = input[argsIndex+1:]

View File

@@ -0,0 +1,54 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package injectionutils
/*
#cgo CFLAGS: -I./libinjection/src
#include <libinjection.h>
#include <stdlib.h>
*/
import "C"
import (
"net/url"
"strings"
"unsafe"
)
// DetectXSS detect XSS in string
func DetectXSS(input string) bool {
if len(input) == 0 {
return false
}
if detectXSSOne(input) {
return true
}
// 兼容 /PATH?URI
if (input[0] == '/' || strings.HasPrefix(input, "http://") || strings.HasPrefix(input, "https://")) && len(input) < 4096 {
var argsIndex = strings.Index(input, "?")
if argsIndex > 0 {
var args = input[argsIndex+1:]
unescapeArgs, err := url.QueryUnescape(args)
if err == nil && args != unescapeArgs {
return detectXSSOne(args) || detectXSSOne(unescapeArgs)
} else {
return detectXSSOne(args)
}
}
}
return false
}
func detectXSSOne(input string) bool {
if len(input) == 0 {
return false
}
var cInput = C.CString(input)
defer C.free(unsafe.Pointer(cInput))
return C.libinjection_xss(cInput, C.size_t(len(input))) == 1
}

View File

@@ -0,0 +1,49 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package injectionutils_test
import (
"github.com/TeaOSLab/EdgeNode/internal/waf/injectionutils"
"github.com/iwind/TeaGo/assert"
"runtime"
"testing"
)
func TestDetectXSS(t *testing.T) {
var a = assert.NewAssertion(t)
a.IsFalse(injectionutils.DetectXSS(""))
a.IsFalse(injectionutils.DetectXSS("abc"))
a.IsTrue(injectionutils.DetectXSS("<script>"))
a.IsTrue(injectionutils.DetectXSS("<link>"))
a.IsFalse(injectionutils.DetectXSS("<html><span>"))
a.IsFalse(injectionutils.DetectXSS("&lt;script&gt;"))
a.IsTrue(injectionutils.DetectXSS("/path?onmousedown=a"))
a.IsTrue(injectionutils.DetectXSS("/path?onkeyup=a"))
a.IsTrue(injectionutils.DetectXSS("onkeyup=a"))
a.IsTrue(injectionutils.DetectXSS("<iframe scrolling='no'>"))
a.IsFalse(injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>"))
}
func BenchmarkDetectXSS_MISS(b *testing.B) {
b.Log(injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>"))
runtime.GOMAXPROCS(4)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span></body></html>")
}
})
}
func BenchmarkDetectXSS_HIT(b *testing.B) {
b.Log(injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span><script src=\"\"></script></body></html>"))
runtime.GOMAXPROCS(4)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = injectionutils.DetectXSS("<html><body><span>RequestId: 1234567890</span><script src=\"\"></script></body></html>")
}
})
}

View File

@@ -590,6 +590,28 @@ func (this *Rule) Test(value any) bool {
default:
return injectionutils.DetectSQLInjection(this.stringifyValue(value))
}
case RuleOperatorContainsXSS:
if value == nil {
return false
}
switch xValue := value.(type) {
case []string:
for _, v := range xValue {
if injectionutils.DetectXSS(v) {
return true
}
}
return false
case [][]byte:
for _, v := range xValue {
if injectionutils.DetectXSS(string(v)) {
return true
}
}
return false
default:
return injectionutils.DetectXSS(this.stringifyValue(value))
}
case RuleOperatorContainsBinary:
data, _ := base64.StdEncoding.DecodeString(this.stringifyValue(this.Value))
if this.IsCaseInsensitive {

View File

@@ -26,6 +26,7 @@ const (
RuleOperatorContainsAllWords RuleOperator = "contains all words"
RuleOperatorNotContainsAnyWord RuleOperator = "not contains any word"
RuleOperatorContainsSQLInjection RuleOperator = "contains sql injection"
RuleOperatorContainsXSS RuleOperator = "contains xss"
RuleOperatorInIPList RuleOperator = "in ip list"
RuleOperatorHasKey RuleOperator = "has key" // has key in slice or map
RuleOperatorVersionGt RuleOperator = "version gt"