WAF规则操作符
WAF规则操作符是指被检查参数与对比值之间的对比方法。
规则操作符可以在添加规则和修改规则时在表单中选择。
数值大于
- 名称:数值大于
- 代号:
gt
- 描述:使用数值对比大于,对比值需要是一个数字
示例
比如我们需要判断一个URL某个参数值大于10:
- 参数:
单个URL参数值 - [arg]
- 参数名:
value
- 操作符:
数值大于
- 对比值:
10
那么:
https://example.com/?value=11 // 匹配
https://example.com/?value=10 // 不匹配
https://example.com/?value=9 // 不匹配
数值大于等于
- 名称:数值大于等于
- 代号:
gte
- 描述:使用数值对比大于等于,对比值需要是一个数字
示例
比如我们需要判断一个URL某个参数值大于等于10:
- 参数:
单个URL参数值 - [arg]
- 参数名:
value
- 操作符:
数值大于等于
- 对比值:
10
那么:
https://example.com/?value=11 // 匹配
https://example.com/?value=10 // 匹配
https://example.com/?value=9 // 不匹配
数值小于
- 名称:数值小于
- 代号:
lt
- 描述:使用数值对比小于,对比值需要是一个数字
示例
比如我们需要判断一个URL某个参数值小于10:
- 参数:
单个URL参数值 - [arg]
- 参数名:
value
- 操作符:
数值小于
- 对比值:
10
那么:
https://example.com/?value=11 // 不匹配
https://example.com/?value=10 // 不匹配
https://example.com/?value=9 // 匹配
数值小于等于
- 名称:数值小于等于
- 代号:
lte
- 描述:使用数值对比小于等于,对比值需要是一个数字
示例
比如我们需要判断一个URL某个参数值小于等于10:
- 参数:
单个URL参数值 - [arg]
- 参数名:
value
- 操作符:
数值小于等于
- 对比值:
10
那么:
https://example.com/?value=11 // 不匹配
https://example.com/?value=10 // 匹配
https://example.com/?value=9 // 匹配
数值等于
- 名称:数值等于
- 代号:
eq
- 描述:使用数值对比等于,对比值需要是一个数字
示例
比如我们需要判断一个URL某个参数值等于10:
- 参数:
单个URL参数值 - [arg]
- 参数名:
value
- 操作符:
数值等于
- 对比值:
10
那么:
https://example.com/?value=abc // 不匹配
https://example.com/?value=10abc // 不匹配
https://example.com/?value=11 // 不匹配
https://example.com/?value=10 // 匹配
https://example.com/?value=10.123 // 不匹配
https://example.com/?value=9 // 不匹配
数值不等于
- 名称:数值不等于
- 代号:
neq
- 描述:使用数值对比不等于,对比值需要是一个数字
示例
比如我们需要判断一个URL某个参数值不等于10:
- 参数:
单个URL参数值 - [arg]
- 参数名:
value
- 操作符:
数值不等于
- 对比值:
10
那么:
https://example.com/?value=11 // 匹配
https://example.com/?value=10 // 不匹配
https://example.com/?value=9 // 匹配
字符串等于
- 名称:字符串等于
- 代号:
eq string
- 描述:使用字符串对比等于
示例
比如我们需要判断一个URL路径中是否和 /js
字符串完全一样:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
字符串等于
- 对比值:
/js
那么:
https://example.com/js # 匹配
https://example.com/js1 # 不匹配
https://example.com/JS # 不匹配
https://example.com/static/js # 不匹配
如果要允许 /JS
和 /Js
也都能匹配,可以设置规则中的 不区分大小写
。
字符串不等于
- 名称:字符串不等于
- 代号:
neq string
- 描述:使用字符串对比不等于
示例
比如我们需要判断一个URL路径中是否和 /js
字符串不一样:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
字符串等于
- 对比值:
/js
那么:
https://example.com/js # 不匹配
https://example.com/js1 # 匹配
https://example.com/JS # 匹配
https://example.com/static/js # 匹配
如果要允许 /JS
和 /Js
也都不匹配,可以设置规则中的 不区分大小写
。
正则匹配
- 名称:正则匹配
- 代号:
match
- 描述:使用正则表达式匹配,在头部使用(?i)表示不区分大小写,正则表达式语法
示例1
比如我们需要判断一个URL路径中是否包含 /script
或 js
:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
正则匹配
- 对比值:
/script|/js
(用|
符号表示或
的关系)
那么:
https://example.com/js # 匹配
https://example.com/script # 匹配
https://example.com/static/script/search # 匹配
https://example.com/static/javascript # 匹配,包含了 script
https://example.com/static/scriptfiles # 匹配,包含了 script
https://example.com/static/scr # 不匹配
https://example.com/static/SCRIPT # 不匹配
如果要允许 /SCRIPT
和 /JS
也都匹配,可以设置规则中的 不区分大小写
。
示例2
比如我们需要判断用户的User-Agent中是否包含一些常用的手机浏览器标识:
- 参数:
客户端信息 - [userAgent]
- 操作符:
正则匹配
- 对比值:
iPhone|iPad|Android
(用|
符号表示或
的关系)
那么:
Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 # 匹配
Mozilla/5.0 (iPhone; CPU iPhone OS 16_2 like Mac OS X) AppleWebKit/605.1.15 # 匹配
Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 # 匹配
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/605.1.15 # 不匹配
如果要允许 iphone
和 android
也都匹配,可以设置规则中的 不区分大小写
。
正则不匹配
- 名称:正则不匹配
- 代号:
not match
- 描述:使用正则表达式不匹配,在头部使用(?i)表示不区分大小写,正则表达式语法
示例
比如我们需要判断一个URL路径中是否不包含 /script
或 js
:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
正则不匹配
- 对比值:
/script|/js
(用|
符号表示或
的关系)
那么:
https://example.com/js # 不匹配
https://example.com/script # 不匹配
https://example.com/static/script/search # 不匹配
https://example.com/static/javascript # 不匹配,包含了 script
https://example.com/static/scriptfiles # 不匹配,包含了 script
https://example.com/static/scr # 匹配
https://example.com/static/SCRIPT # 匹配
如果要允许 /SCRIPT
和 /JS
也都不匹配,可以设置规则中的 不区分大小写
。
包含字符串
- 名称:包含字符串
- 代号:
contains
- 描述:包含某个字符串,比如Hello World包含了World;每个规则只能填入一个被包含字符串;不能使用正则表达式
示例
比如我们需要判断一个URL路径中是否包含 /js
:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
包含字符串
- 对比值:
/js
那么:
https://example.com/js # 匹配
https://example.com/static/js/search # 匹配
https://example.com/static/jscripts # 匹配,包含了 js
https://example.com/static/JS # 不匹配
https://example.com/static/sj # 不匹配
如果要允许 /JS
和 /Js
也都匹配,可以设置规则中的 不区分大小写
。
不包含字符串
- 名称:不包含字符串
- 代号:
not contains
- 描述:不包含某个字符串,比如Hello字符串中不包含Hi;每个规则只能填入一个被检查字符串;不能使用正则表达式
示例
比如我们需要判断一个URL路径中是否不包含 /js
:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
不包含字符串
- 对比值:
/js
那么:
https://example.com/js # 不匹配
https://example.com/static/js/search # 不匹配
https://example.com/static/jscripts # 不匹配,包含了 js
https://example.com/static/JS # 匹配
https://example.com/static/sj # 匹配
如果要允许 /JS
和 /Js
也都不匹配,可以设置规则中的 不区分大小写
。
包含任一字符串
- 名称:包含任一字符串
- 代号:
contains any
- 描述:包含字符串列表中的任意一个,比如/hello/world包含/hello和/hi中的/hello,每行一个字符串
示例
比如我们需要判断一个URL路径中是否包含 /js
或 /script
:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
包含任一字符串
- 对比值:使用换行隔开多个值:
/js /script
那么:
https://example.com/js # 匹配
https://example.com/static/js/search # 匹配
https://example.com/static/jscripts # 匹配,包含了 js和script
https://example.com/static/script # 匹配,包含了 script
https://example.com/static/JS # 不匹配
https://example.com/static/sj # 不匹配
如果要允许 /SCRIPT
和 /Js
也都匹配,可以设置规则中的 不区分大小写
。
包含所有字符串
- 名称:包含所有字符串
- 代号:
contains all
- 描述:包含字符串列表中的所有字符串,比如/hello/world必须包含/hello和/world,每行一个字符串
示例
比如我们需要判断一个URL路径中是否同时包含 /js
和 /script
:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
包含所有字符串
- 对比值:使用换行隔开多个值:
/js /script
那么:
https://example.com/js # 不匹配
https://example.com/static/js/search # 不匹配
https://example.com/js/script # 匹配,同时包含了 js和script
https://example.com/static/jscripts # 匹配,同时包含了 js和script
https://example.com/static/script # 不匹配
https://example.com/static/JS # 不匹配
https://example.com/static/sj # 不匹配
如果要允许 /JS/SCRIPT
也都匹配,可以设置规则中的 不区分大小写
。
包含前缀
- 名称:包含前缀
- 代号:
prefix
- 描述:包含字符串前缀部分,比如/hello前缀会匹配/hello, /hello/world等;每个规则只能填入一个前缀;不能使用正则表达式
示例
比如我们需要判断一个URL路径中是否以 /js
开头:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
包含前缀
- 对比值:
/js
那么:
https://example.com/js # 匹配
https://example.com/static/js/search # 不匹配
https://example.com/static/JS # 不匹配
https://example.com/static/sj # 不匹配
如果要允许 /JS
和 /Js
也都匹配,可以设置规则中的 不区分大小写
。
包含后缀
- 名称:包含后缀
- 代号:
suffix
- 描述:包含字符串后缀部分,比如/hello后缀会匹配/hello, /hi/hello等;每个规则只能填入一个前缀;不能使用正则表达式
示例
比如我们需要判断一个URL路径中是否以 /js
结尾:
- 参数:
请求路径 - [requestPath]
(因为这里我们不需要判断域名,所以没有使用请求完整URL
) - 操作符:
包含后缀
- 对比值:
/js
那么:
https://example.com/js # 匹配
https://example.com/static/js # 匹配
https://example.com/js/search # 不匹配
https://example.com/static/JS # 不匹配
https://example.com/static/sj # 不匹配
如果要允许 /JS
和 /Js
也都匹配,可以设置规则中的 不区分大小写
。
包含任一单词
- 名称:包含任一单词
- 代号:
contains any word
- 描述:包含某个独立单词,对比值中每行一个单词,比如mozilla firefox里包含了mozilla和firefox两个单词,但是不包含fire和fox这两个单词
- 版本:GoEdge v1.3.2
示例
比如我们需要判断一个User-Agent是否包含Chrome
和Firefox
两个单词中的一个:
- 参数:
客户端信息 - [userAgent]
- 操作符:
包含任一单词
- 对比值:使用换行隔开多个值:
Chrome Firefox
那么:
Mozilla/5.0 Chrome/119.0.0.0 Safari/537.36 # 匹配
Mozilla/5.0 Firefox/120.0 # 匹配
Mozilla/5.0 Safari/605.1.15 # 不匹配
Mozilla/5.0 FakeFirefox/120.0 # 不匹配(因为不是单独的Firefox)
Mozilla/5.0 firefox/120.0 # 不匹配(因为firefox首字母大小写不相同,除非设置了不区分大小写)
包含所有单词
- 名称:包含所有单词
- 代号:
contains all words
- 描述:包含所有的独立单词,对比值中每行一个单词,比如mozilla firefox里包含了mozilla和firefox两个单词,但是不包含fire和fox这两个单词
- 版本:GoEdge v1.3.2
示例
比如我们需要判断一个User-Agent是否同时包含Chrome
和Safari
两个单词:
- 参数:
客户端信息 - [userAgent]
- 操作符:
包含所有单词
- 对比值:使用换行隔开多个值:
Chrome Safari
那么:
Mozilla/5.0 Chrome/119.0.0.0 Safari/537.36 # 匹配(同时包含Chrome和Safari)
Mozilla/5.0 Firefox/120.0 # 不匹配
Mozilla/5.0 Safari/605.1.15 # 不匹配(只匹配到一个)
Mozilla/5.0 Chrome/119.0.0.0 FakeSafari/537.36 # 不匹配(因为不是单独的Safari)
Mozilla/5.0 Chrome/119.0.0.0 safari/537.36 # 不匹配(因为safari首字母大小写不相同,除非设置了不区分大小写)
不包含任一单词
- 名称:不包含任一单词
- 代号:
contains any word
- 描述:不包含某个独立单词,对比值中每行一个单词,比如mozilla firefox里包含了mozilla和firefox两个单词,但是不包含fire和fox这两个单词
- 版本:GoEdge v1.3.2
示例
比如我们需要判断一个User-Agent是否不包含Chrome
和Firefox
两个单词中的一个:
- 参数:
客户端信息 - [userAgent]
- 操作符:
不包含任一单词
- 对比值:使用换行隔开多个值:
Chrome Firefox
那么:
Mozilla/5.0 Chrome/119.0.0.0 Safari/537.36 # 不匹配
Mozilla/5.0 Firefox/120.0 # 不匹配
Mozilla/5.0 Safari/605.1.15 # 匹配
Mozilla/5.0 FakeFirefox/120.0 # 匹配(因为不是单独的Firefox)
Mozilla/5.0 firefox/120.0 # 匹配(因为firefox首字母大小写不相同,除非设置了不区分大小写)
包含SQL注入
- 名称:包含SQL注入
- 代号:
contains sql injection
- 描述:检测字符串内容是否包含SQL注入
- 版本:GoEdge v1.3.2
示例
比如我们要检测用户的访问URL中是否包含SQL注入,可以添加以下规则:
- 参数:
请求URI - [requestURI]
- 操作符:
包含SQL注入
- 对比值:不需要填写
那么:
/index?id=123 or 1=1 # 匹配
/index?id=123%20or%201=1 # 匹配(会自动对URL中参数进行解码)
/index?id=123 union select # 匹配
/index?id=123 # 不匹配(正常参数)
包含SQL注入-严格模式
- 名称:包含SQL注入
- 代号:
contains sql injection strictly
- 描述:更加严格地检测字符串内容是否包含SQL注入,相对于非严格模式,有一定的误报几率
- 版本:GoEdge v1.3.3
包含XSS注入
- 名称:包含XSS注入
- 代号:
contains xss
- 描述:检测字符串内容是否包含XSS注入
- 版本:GoEdge v1.3.2
示例
比如我们要检测用户的访问URL中是否包含XSS注入,可以添加以下规则:
- 参数:
请求URI - [requestURI]
- 操作符:
包含XSS注入
- 对比值:不需要填写
那么:
/index?id=123%20<script # 匹配(包含<script)
/index?<html><body><link></body></html> # 匹配(包含<link>)
/index?<html><body></body></html> # 不匹配(没有外链标签)
/index?id=123 # 不匹配(正常参数)
包含XSS注入-严格模式
- 名称:包含XSS注入
- 代号:
contains xss strictly
- 描述:更加严格地检测字符串内容是否包含XSS注入,相对于非严格模式,此时xml、audio、video等标签也会被匹配
- 版本:GoEdge v1.3.3
示例
比如我们要检测用户的访问URL中是否包含XSS注入,可以添加以下规则:
- 参数:
请求URI - [requestURI]
- 操作符:
包含XSS注入-严格模式
- 对比值:不需要填写
那么:
/index?id=123%20<script # 匹配(包含<script)
/index?<html><body><link></body></html> # 匹配(包含<link>)
/index?<html><body></body></html> # 不匹配(没有外链标签)
/index?id=123 # 不匹配(正常参数)
/index?id=<xml>123</xml> # 匹配(严格模式下对XML、AUDIO等标签也会匹配)
包含二进制数据
- 名称:包含二进制数据
- 代号:
contains binary
- 描述:包含一组二进制数据
不包含二进制数据
- 名称:不包含二进制数据
- 代号:
not contains binary
- 描述:不包含一组二进制数据
包含索引
- 名称:包含索引
- 代号:
has key
- 描述:对于一组数据拥有某个键值或者索引
版本号大于
- 名称:版本号大于
- 代号:
version gt
- 描述:对比版本号大于
版本号小于
- 名称:版本号小于
- 代号:
version lt
- 描述:对比版本号小于
版本号范围
- 名称:版本号范围
- 代号:
version range
- 描述:判断版本号在某个范围内,格式为version1,version2
IP等于
- 名称:IP等于
- 代号:
eq ip
- 描述:将参数转换为IP进行对比,只能对比单个IP
在一组IP中
- 名称:在一组IP中
- 代号:
in ip list
- 描述:判断参数IP在一组IP内,每行一个IP
示例
比如我们需要判断客户端地址是否在一组IP内:
- 参数:
客户端地址(IP)- [remoteAddr]
- 操作符:
在一组IP中
- 对比值:填入多行,每行一个IP:
192.168.2.40 192.168.3.50 192.168.4.100
那么:
192.168.2.40 # 匹配
192.168.3.50 # 匹配
192.168.4.100 # 匹配
192.168.2.101 # 不匹配
192.168.1.100 # 不匹配
IP大于
- 名称:IP大于
- 代号:
gt ip
- 描述:将参数转换为IP进行对比
IP大于等于
- 名称:IP大于等于
- 代号:
gte ip
- 描述:将参数转换为IP进行对比
IP小于
- 名称:IP小于
- 代号:
lt ip
- 描述:将参数转换为IP进行对比
IP小于等于
- 名称:IP小于等于
- 代号:
lte ip
- 描述:将参数转换为IP进行对比
IP范围
注意:在GoEdge v0.6.0以前,”IP范围”操作符对比值中只能填写单个IP范围;在v0.6.0以后可以填写多个IP范围,每行一个。
- 名称:IP范围
- 代号:
ip range
- 描述:IP在某个范围之内,范围格式可以是英文逗号分隔的
开始IP,结束IP
,比如192.168.1.100,192.168.2.200
;或者CIDR格式的ip/bits,比如192.168.2.1/24
;或者单个IP。可以填写多行,每行一个IP范围。
示例1 - CIDR
比如我们需要判断客户端地址是否在一个范围内:
- 参数:
客户端地址(IP)- [remoteAddr]
- 操作符:
IP范围
- 对比值:
192.168.2.1/24
那么:
192.168.2.40 # 匹配
192.168.1.100 # 不匹配
示例2 - IP段
比如我们需要判断客户端地址是否在一个范围内:
- 参数:
客户端地址(IP)- [remoteAddr]
- 操作符:
IP范围
- 对比值:
192.168.2.1,192.168.2.100
(表示从192.168.2.1
到192.168.2.100
)
那么:
192.168.2.40 # 匹配
192.168.2.101 # 不匹配
192.168.1.100 # 不匹配
对比值也可以用中划线分隔,类似于192.168.2.1-192.168.2.100
。
示例3 - 多个IP
比如我们需要判断客户端地址是否在一组范围内:
- 参数:
客户端地址(IP)- [remoteAddr]
- 操作符:
IP范围
- 对比值:填入多行,既可以是CIDR格式,也可以是IP段,还可以是单个IP:
192.168.2.40 192.168.3.1/24 192.168.4.100-192.168.4.200
那么:
192.168.2.40 # 匹配
192.168.3.50 # 匹配
192.168.4.100 # 匹配
192.168.2.101 # 不匹配
192.168.1.100 # 不匹配
不在IP范围
注意:在GoEdge v0.6.0以前,”不在IP范围”操作符对比值中只能填写单个IP范围;在v0.6.0以后可以填写多个IP范围,每行一个。
- 名称:不在IP范围
- 代号:
not ip range
- 描述:IP不在某个范围之内,范围格式可以是英文逗号分隔的
开始IP,结束IP
,比如192.168.1.100,192.168.2.200
;或者CIDR格式的ip/bits,比如192.168.2.1/24
;或者单个IP。可以填写多行,每行一个IP范围。
具体示例请参考本文的 IP范围。
IP取模10
- 名称:IP取模10
- 代号:
ip mod 10
- 描述:对IP参数值取模,除数为10,对比值为余数
IP取模100
- 名称:IP取模100
- 代号:
ip mod 100
- 描述:对IP参数值取模,除数为100,对比值为余数
IP取模
- 名称:IP取模
- 代号:
ip mod
- 描述:对IP参数值取模,对比值格式为:除数,余数,比如10,1