WAF开发之自学习模式开发实战
字数 1583 2025-08-18 11:37:20
WAF自学习模式开发实战教学文档
一、自学习模式概述
1.1 传统WAF白名单功能的问题
- 基于概率统计学的传统方法存在两个主要问题:
- 学习时间过长,业务频繁变更时模型难以收敛
- 误报率较高,导致用户下线功能
1.2 自学习模式的目标
- 无需或只需少量用户干预
- 降低WAF漏报率
- 提升检测速度
1.3 jxwaf自学习模式的创新点
- 不采用概率统计学方法
- 实现三个维度的分析:
- 正则自适应匹配
- 长度分析
- 词法分析
二、核心实现原理
2.1 基本思路
- 通过分析用户输入中的特殊字符来区分正常数据和攻击语句
- 防护关键:识别用户输入中的特殊字符
2.2 正则自适应匹配
2.2.1 学习过程
local function white_learn_rx(value)
local learn_value = value
local level
local level_one = _white_config.level_one or [=[\W]=]
local level_two = _white_config.level_two or [==[[^\w ]==]
local level_three = _white_config.level_three or [==[[^\w ]==]
local level_four = _white_config.level_four or [==[<>=]=]
if (not ngx.re.find(learn_value, level_one,"oij")) then
level = 1
elseif (not ngx.re.find(learn_value, level_two,"oij")) then
level = 2
elseif (not ngx.re.find(learn_value, level_three,"oij")) then
level = 3
elseif (not ngx.re.find(learn_value, level_four,"oij")) then
level = 4
else
level = 6
end
return level
end
2.2.2 五层匹配规则
- 第一层:参数值为数字、字母和_组成
- 第二层:参数值为数字、字母和_、"、()、.组成
- 第三层:参数值为数字、字母和_组成(含常见特殊字符)
- 第四层:参数值不包含<、>、=等危险特殊字符
- 第五层:含任意字符
2.2.3 检测过程
local function white_check_rx(value,level)
local check_value = value
local check_level = level
local level_one = _white_config.level_one or [=[\W]=]
local level_two = _white_config.level_two or [==[[^\w ]==]
local level_three = _white_config.level_three or [==[[^\w ]==]
local level_four = _white_config.level_four or [==[<>=]=]
local result = nil
if check_level == 1 and ngx.re.find(check_value, level_one,"oij") then
result = 1
elseif check_level == 2 and ngx.re.find(check_value, level_two,"oij") then
result = 2
elseif check_level == 3 and ngx.re.find(check_value, level_three,"oij") then
result = 3
elseif check_level == 4 and ngx.re.find(check_value, level_four,"oij") then
result = 4
elseif type(check_level) == string and ngx.re.find(check_value,check_level,"oij") then
result = 5
else
end
return result
end
2.3 长度分析
2.3.1 相关配置
Learn length bypass: true/false(检测到异常只告警不拦截)Learn length bypass length: 数字(默认30,小于该值不处理)Learn length limit: 数字(默认1500,参数值最大长度)Learn length update count: 数字(默认5,长度参数迭代次数)
2.3.2 实现特点
- 新参数值长度比旧值大时会覆盖旧长度
- 迭代次数超过限制时,长度值将被设置为
Learn length limit
2.4 词法分析
2.4.1 核心处理函数
local function _process_string(arg)
local result = {}
local _arg = arg
local char = nil
for count=1,#_arg,1 do
local tmp = string.byte(_arg,count)
if (tmp >= 0 and tmp <= 31) or tmp == 127 then
-- control
if char ~= 'c' then
table.insert(result,'c')
char = 'c'
end
elseif (tmp >= 48 and tmp <= 57) or (tmp >= 65 and tmp <= 90) or (tmp >= 97 and tmp <= 122) or tmp > 127 then
-- normal
if char ~= 'n' then
table.insert(result,'n')
char = 'n'
end
elseif (tmp >= 32 and tmp <=34) or tmp == 40 or tmp == 41 or tmp == 44 or tmp == 46 or tmp == 64 or tmp == 95 or tmp == 63 then
-- usual char (space)
if char ~= 'u' then
table.insert(result,'u')
char = 'u'
end
elseif (tmp >= 35 and tmp <= 39 ) or tmp == 42 or tmp == 43 or tmp== 45 or tmp == 47 or (tmp >= 58 and tmp <= 62) or (tmp >= 91 and tmp <=96) or (tmp >= 123 and tmp <= 126) then
-- anomaly char
if char ~= 'a' then
table.insert(result,'a')
char = 'a'
end
else
ngx.log(ngx.ERR,"process string error ",_arg)
end
end
return table.concat(result)
end
2.4.2 字符分类规则
- 控制字符(0~31及127):标记为'c'
- 数字、字母、中文等:标记为'n'
- 空格等常见字符:标记为'u'
- 其他特殊字符:标记为'a'
2.4.3 特征合并
- 相同特征合并为一个,如"aaaaaabbbbb哇哇哇哇"→"n"
- 特征数超过5个时,检测进入bypass模式
三、全局配置
3.1 主要配置项
Force_reject: true/false(默认为false,未被学习到的参数和URL请求是否拒绝)Igonre uri: 正则(Force_reject为true时,匹配该正则的URL请求放行)check_reject: true/false(默认为true,未能通过检测的请求是否拒绝)learn_count: 数字(默认为1000,同一URL请求的学习迭代次数)
四、案例分析(以DVWA登录接口为例)
4.1 学习过程
- 初始学习数据示例:
"Login":[1,5,["n"],"false"] "user_token":[1,32,["n"],"false"] "username":[1,5,["n"],"false"] "password":[1,8,["n"],"false"]
4.2 学习后数据变化
- Login参数:固定值"Login",学习数据不变
- user_token:32位十六进制数据,学习数据不变
- username参数:
- 正则自适应匹配值由1→3
- 长度达到21
- 词法特征增加"nunun"
- password参数:
- 正则自适应匹配值由1→6(任意字符)
- 长度维度失效
- 词法分析维度失效
4.3 攻击检测示例
- SQL注入:
' and 1=(select @@VERSION)- 正则匹配值:6
- 长度:24
- 词法特征:"aununununu"
- 结果:拒绝
- 命令执行:
ls -al- 正则匹配值:3
- 长度:6
- 词法特征:"nun"
- 结果:拒绝
- 代码执行:
phpinfo()- 正则匹配值:2
- 长度:9
- 词法特征:"nu"
- 结果:拒绝
五、总结
5.1 解决的问题
- 模型收敛问题:通过增量更新(边检测边学习)
- 误报问题:采用"宁放过不错杀"原则
5.2 引入的新问题
- 提高了用户介入度
- 提高了漏报率
5.3 整体防护策略
- 黑名单+全局白名单+自学习+机器学习多层防护
- 性能消耗低(相当于多1-2条规则)
- 支持管理界面审计功能优化