模拟WAF一次策略命中 - shengnoah/blues GitHub Wiki
作者:糖果
WAF策略规则的式可以用多种描述形式描述,比如XML、YAML、纯文本、JSON等形式。而我们 这次模拟测试选择的规则的存储形式是JSON:
[{
"Id":25,
"RuleType":"args",
"RuleItem":"(onmouseover|onerror|onload)\\="
}]
这种规则样式来至于XWAF的规则存储形式,在文章的最后我们提供了XWAF的相关信息,追溯 到更早是LoveShell的WAF形式,够成了这条规则的基础数,就是纯“(onmouseover|onerror|onload)\=” 正则数据来至于loveshell的WAF项目。
完成这次模拟工作,我们需要几个大体的处理过程。
-
生成规则文件。
-
读取规则到Openresty的Share.Diction中。
-
截取用户访问数据。
-
判断计算用户请求数据是否命中策略。
1.生成规则文件。
为了下一步WAF功能的发展, 我们没有直接的用纯XWAF的JSON规则,而是我们在原有的基础上 加入一个新的字段来描述策略,就是Action这个字段,表示的是,策略命中是, WAF应该做出 什么动作。
ruler主要的作用是把文件中的原始转换成新的JSON数据形式,就是加了一个Action。
[{
"Id":25,
"RuleType":"args",
"RuleItem":"(onmouseover|onerror|onload)\\=",
"Action":1
}]
ruler.lua
local ruler = {}
function ruler.read(self, var)
print(var)
file = io.open(var,"r")
if file==nil then
return
end
t = {}
for line in file:lines() do
table.insert(t,line)
end
file:close()
return(t)
end
function ruler.write(self,var, rule)
file = io.open(var,"aw")
if file==nil then
return
end
file:write(rule,"\n")
file:close()
return(t)
end
function ruler.dump(self, in_name, out_name)
print(name)
local ret = self:read(in_name)
rules = {}
local idx = 0
for k,v in pairs(ret) do
idx = idx + 1
item = {Id=idx, RuleType="args", RuleItem=v, Action=1}
table.insert(rules,item)
end
for k,v in pairs(rules) do
for key,value in pairs(v) do
print(key, value)
end
end
self:export(out_name, rules)
end
function ruler.export(self, filename, rule_name)
local json = require"cjson"
local ret = json.encode(rule_name)
self:write(filename, ret)
end
function ruler.loading(self, filename)
local json = require"cjson"
local util = require "cjson.util"
local ret = util.file_load(filename, env)
local data = json.decode(ret)
print(util.serialise_value(data))
end
return ruler
测试如何用旧的JSON生成新的JSON。 test.lua
local ruler = require"ruler"
ruler::export("args.rule", "testcase")
2.读取规则到Openresty的Share.Diction中。
这部分的内容,我们是先用Blues正常的GET访问,模拟数据的加载,然后再把测试成功的代码 移到Init.lua中,把Content阶段执行的代码,放到Init中。
app.lua
app:get("/xwaf", function(request,id)
local json_text = bjson.loadf("./app/data/rules/args.rule", env)
local t = bjson.decode(json_text)
buffer.sett("args", t)
meta = buffer.gett("args")
ngx.say(bjson.pprint(meta))
end)
app:get("/ltbl", function(request,id)
local json_text = {Id=25, RuleType="args", RuleItem="(onmouseover|onerror|onload)\\="}
local t = bjson.decode(json_text)
buffer.sett("args", t)
meta = buffer.gett("args")
ngx.say(bjson.pprint(meta))
end)
XWAF有不单一个rules文件,我们选中了其中的args这个文件进行了读取,下面我们要在init.lua中读取这些数据,在init阶段读取,在content阶段的app.lua中读取这个args结构:
init.lua
local buffer = require "buffer"
local bjson = require "utils.bjson"
local json_text = bjson.loadf("./app/data/rules/testcase", env)
local t = bjson.decode(json_text)
buffer.sett("rule", t)
buffer.set("candylab", "Candylab:Blues")
--这是针对读取args规则的三句新加代码
local json_text = bjson.loadf("./app/data/rules/args.rule", env)
local t = bjson.decode(json_text)
buffer.sett("init_args", t)
3.截取用户访问数据。
在Init阶段如果我们已经将rule数据加入字典的话,在blues框架只要简单的访问一下字段中的数据就可以。
app.lua
app:get("/xwaf_rules", function(request,id)
meta = buffer.gett("init_args")
ngx.say(bjson.pprint(meta))
end)
我们要做数据过滤,而且是基于正则的,所以在项目最开始阶段,直接引入了XWAF的规则文件。在content阶段的读取的这些数据,在init阶段同样可以读取。
而下面的数据碰撞就是针对这个args规则进行演示的,我们继续在content阶段,用一个GET方法请求模拟这个WAF规则命中的过程,不选POST而选GET,因为GET取参数简单,便于集中经历说明规则进行简单的比较,而不是把重点放在解析POST过来的参数和内容上。
app:get("/greatball", function(request,id)
meta = buffer.gett("init_args")
ngx.say(bjson.pprint(meta))
ngx.say(request.params.cmd_url)
end)
4.判断计算用户请求数据是否命中策略。
我们创建一个有greatball的请求,我们简单的模拟一些这个请求数据与WAF规则对比的过程。 在这个方法里,我们同时取得了,url和args这个规则所有的数据,下面就是按什么样的方式 进行数据配对了。
下面是代码实现,我们模拟的是在GET请求到的路由处理函数,直接读取规则,然后和用户 提供的请求从比较。
app:get("/greatball", function(request,id)
local json_text = bjson.loadf("./app/data/rules/args.rule", env)
local ret = bjson.decode(json_text)
for _,rule in pairs(ret) do
regular = rule["RuleItem"]
if regular ~= "" and ngx.re.find(request.params.cmd_url, regular, "jo") then
ngx.say("命中!")
end
end
end)
下个实验,我们会把这种策略命中的处理代码,独立成一个单独的功能文件,脱离Blues的路由系统,后 可以直接把这部分过滤用的代码做为Blues自己的安全审计模块,那就是下一篇要介绍的内容。
XWAF是一款开源的WAF产品,详细的介绍大家参考: 开源WEB防火墙XWAF介绍 ,作者的官方的站点:XWAF官网。
PS:转载到其它平台请注明作者姓名及原文链接,请勿用于商业用途。