mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-08 03:00:27 +08:00
修复WAF中反斜杠符号(\)有可能解析错误的Bug
This commit is contained in:
@@ -57,6 +57,79 @@ func TestRegexp_ParseKeywords(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRegexp_Special(t *testing.T) {
|
||||||
|
var unescape = func(v string) string {
|
||||||
|
//replace urlencoded characters
|
||||||
|
|
||||||
|
var chars = [][2]string{
|
||||||
|
{`\s`, `(\s|%09|%0A|\+)`},
|
||||||
|
{`\(`, `(\(|%28)`},
|
||||||
|
{`=`, `(=|%3D)`},
|
||||||
|
{`<`, `(<|%3C)`},
|
||||||
|
{`\*`, `(\*|%2A)`},
|
||||||
|
{`\\`, `(\\|%2F)`},
|
||||||
|
{`!`, `(!|%21)`},
|
||||||
|
{`/`, `(/|%2F)`},
|
||||||
|
{`;`, `(;|%3B)`},
|
||||||
|
{`\+`, `(\+|%20)`},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range chars {
|
||||||
|
if !strings.Contains(v, c[0]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var pieces = strings.Split(v, c[0])
|
||||||
|
|
||||||
|
// 修复piece中错误的\
|
||||||
|
for pieceIndex, piece := range pieces {
|
||||||
|
var l = len(piece)
|
||||||
|
if l == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if piece[l-1] != '\\' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算\的数量
|
||||||
|
var countBackSlashes = 0
|
||||||
|
for i := l - 1; i >= 0; i-- {
|
||||||
|
if piece[i] == '\\' {
|
||||||
|
countBackSlashes++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if countBackSlashes%2 == 1 {
|
||||||
|
// 去掉最后一个
|
||||||
|
pieces[pieceIndex] = piece[:len(piece)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v = strings.Join(pieces, c[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range []string{
|
||||||
|
`\\s`,
|
||||||
|
`\s\W`,
|
||||||
|
`aaaa/\W`,
|
||||||
|
`aaaa\/\W`,
|
||||||
|
`aaaa\=\W`,
|
||||||
|
`aaaa\\=\W`,
|
||||||
|
`aaaa\\\=\W`,
|
||||||
|
`aaaa\\\\=\W`,
|
||||||
|
} {
|
||||||
|
var es = unescape(s)
|
||||||
|
t.Log(s, "=>", es)
|
||||||
|
_, err := re.Compile(es)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRegexp_ParseKeywords2(t *testing.T) {
|
func TestRegexp_ParseKeywords2(t *testing.T) {
|
||||||
var a = assert.NewAssertion(t)
|
var a = assert.NewAssertion(t)
|
||||||
|
|
||||||
|
|||||||
@@ -590,18 +590,56 @@ func (this *Rule) SetCheckpointFinder(finder func(prefix string) checkpoints.Che
|
|||||||
this.checkpointFinder = finder
|
this.checkpointFinder = finder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unescapeChars = [][2]string{
|
||||||
|
{`\s`, `(\s|%09|%0A|\+)`},
|
||||||
|
{`\(`, `(\(|%28)`},
|
||||||
|
{`=`, `(=|%3D)`},
|
||||||
|
{`<`, `(<|%3C)`},
|
||||||
|
{`\*`, `(\*|%2A)`},
|
||||||
|
{`\\`, `(\\|%2F)`},
|
||||||
|
{`!`, `(!|%21)`},
|
||||||
|
{`/`, `(/|%2F)`},
|
||||||
|
{`;`, `(;|%3B)`},
|
||||||
|
{`\+`, `(\+|%20)`},
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Rule) unescape(v string) string {
|
func (this *Rule) unescape(v string) string {
|
||||||
// replace urlencoded characters
|
// replace urlencoded characters
|
||||||
v = strings.Replace(v, `\s`, `(\s|%09|%0A|\+)`, -1)
|
|
||||||
v = strings.Replace(v, `\(`, `(\(|%28)`, -1)
|
for _, c := range unescapeChars {
|
||||||
v = strings.Replace(v, `=`, `(=|%3D)`, -1)
|
if !strings.Contains(v, c[0]) {
|
||||||
v = strings.Replace(v, `<`, `(<|%3C)`, -1)
|
continue
|
||||||
v = strings.Replace(v, `\*`, `(\*|%2A)`, -1)
|
}
|
||||||
v = strings.Replace(v, `\\`, `(\\|%2F)`, -1)
|
var pieces = strings.Split(v, c[0])
|
||||||
v = strings.Replace(v, `!`, `(!|%21)`, -1)
|
|
||||||
v = strings.Replace(v, `/`, `(/|%2F)`, -1)
|
// 修复piece中错误的\
|
||||||
v = strings.Replace(v, `;`, `(;|%3B)`, -1)
|
for pieceIndex, piece := range pieces {
|
||||||
v = strings.Replace(v, `\+`, `(\+|%20)`, -1)
|
var l = len(piece)
|
||||||
|
if l == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if piece[l-1] != '\\' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算\的数量
|
||||||
|
var countBackSlashes = 0
|
||||||
|
for i := l - 1; i >= 0; i-- {
|
||||||
|
if piece[i] == '\\' {
|
||||||
|
countBackSlashes++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if countBackSlashes%2 == 1 {
|
||||||
|
// 去掉最后一个
|
||||||
|
pieces[pieceIndex] = piece[:len(piece)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v = strings.Join(pieces, c[1])
|
||||||
|
}
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ var cache = ttlcache.NewCache()
|
|||||||
|
|
||||||
// MatchStringCache 正则表达式匹配字符串,并缓存结果
|
// MatchStringCache 正则表达式匹配字符串,并缓存结果
|
||||||
func MatchStringCache(regex *re.Regexp, s string) bool {
|
func MatchStringCache(regex *re.Regexp, s string) bool {
|
||||||
|
if regex == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 如果长度超过4096,大概率是不能重用的
|
// 如果长度超过4096,大概率是不能重用的
|
||||||
if len(s) > 4096 {
|
if len(s) > 4096 {
|
||||||
return regex.MatchString(s)
|
return regex.MatchString(s)
|
||||||
@@ -35,6 +39,10 @@ func MatchStringCache(regex *re.Regexp, s string) bool {
|
|||||||
|
|
||||||
// MatchBytesCache 正则表达式匹配字节slice,并缓存结果
|
// MatchBytesCache 正则表达式匹配字节slice,并缓存结果
|
||||||
func MatchBytesCache(regex *re.Regexp, byteSlice []byte) bool {
|
func MatchBytesCache(regex *re.Regexp, byteSlice []byte) bool {
|
||||||
|
if regex == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 如果长度超过4096,大概率是不能重用的
|
// 如果长度超过4096,大概率是不能重用的
|
||||||
if len(byteSlice) > 4096 {
|
if len(byteSlice) > 4096 {
|
||||||
return regex.Match(byteSlice)
|
return regex.Match(byteSlice)
|
||||||
|
|||||||
Reference in New Issue
Block a user