op防火墙更新1

pull/209/head
midoks 3 years ago
parent 4c73f13f2d
commit b840086d4d
  1. 9
      plugins/op_waf/index.py
  2. 4
      plugins/op_waf/install.sh
  3. 28
      plugins/op_waf/js/op_waf.js
  4. 59
      plugins/op_waf/t/index.py
  5. 173
      plugins/op_waf/waf/lua/common.lua
  6. 115
      plugins/op_waf/waf/lua/init.lua
  7. 2
      plugins/op_waf/waf/rule/user_agent.json

@ -222,6 +222,10 @@ def initDreplace():
if not os.path.exists(logs_path):
mw.execShell('mkdir -p ' + logs_path)
debug_log = path + '/debug.log'
if not os.path.exists(debug_log):
mw.execShell('echo "" > ' + debug_log)
config = path + '/waf/config.json'
content = mw.readFile(config)
content = json.loads(content)
@ -235,6 +239,11 @@ def initDreplace():
content = contentReplace(content)
mw.writeFile(config, content)
config_common = path + "/waf/lua/common.lua"
content = mw.readFile(config_common)
content = contentReplace(content)
mw.writeFile(config_common, content)
waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf"
waf_tpl = getPluginDir() + "/conf/luawaf.conf"
content = mw.readFile(waf_tpl)

@ -19,12 +19,12 @@ Install_of(){
echo '0.1' > $serverPath/op_waf/version.pl
echo 'install ok' > $install_tmp
cd ${rootPath} && python3 plugins/op_waf/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py start
}
Uninstall_of(){
cd ${rootPath} && python3 plugins/op_waf/index.py stop
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop
rm -rf $serverPath/op_waf
}

@ -28,7 +28,7 @@ function setRequestCode(ruleName, statusCode){
title: "设置响应代码【" + ruleName + "】",
area: '300px',
shift: 5,
closeBtn: 2,
closeBtn: 1,
shadeClose: true,
content: '<div class="bt-form pd20 pb70">\
<div class="line">\
@ -144,7 +144,7 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
type: 1,
title: "设置CC规则",
area: '540px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@ -184,7 +184,7 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
type: 1,
title: "设置恶意容忍规则",
area: '500px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@ -339,7 +339,7 @@ function setObjConf(ruleName, type) {
type: 1,
title: "编辑规则【" + ruleName + "】",
area: ['700px', '530px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -405,7 +405,7 @@ function scanRule() {
type: 1,
title: "常用扫描器过滤规则",
area: '650px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@ -571,7 +571,7 @@ function ipWhite(type) {
type: 1,
title: "管理IP白名单",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 ipv4_list">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -714,7 +714,7 @@ function ipBlack(type) {
type: 1,
title: "管理IP黑名单",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="tab_list"><div class="tab_block active">IPv4黑名单</div><div class="tab_block">IPv6</div></div>\
<div class="pd15 ipv4_block">\
@ -824,7 +824,7 @@ function wafScreen(){
<div class="line"><span class="name">CC攻击</span><span class="val">'+rdata.rules.cc+'</span></div>\
<div class="line"><span class="name">恶意User-Agent</span><span class="val">'+rdata.rules.user_agent+'</span></div>\
<div class="line"><span class="name">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">0</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">'+rdata.rules.scan+'</span></div>\
<div class="line"><span class="name">恶意HEAD请求</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">URI保护</span><span class="val">'+rdata.rules.args+'</span></div>\
@ -975,7 +975,7 @@ function siteWafLog(siteName) {
type: 1,
title: "日志【" + siteName + "】",
area: ['880px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="lib-box pd15 lib-box-log">\
<div class="lib-con-title" style="height:40px"><select id="selectLogDay" class="bt-input-text" onchange="siteLogCon(\''+ siteName + '\',this.options[this.options.selectedIndex].value,1)">' + selectLogDay + '</select></div>\
@ -1071,7 +1071,7 @@ function siteLogCon(siteName, day, page) {
type: 1,
title: time + "详情",
area: '600px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
@ -1190,7 +1190,7 @@ function siteRuleAdmin(siteName, ruleName, type) {
type: 1,
title: "管理网站过滤规则【" + title + "】",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -1237,7 +1237,7 @@ function cdnHeader(siteName, type) {
type: 1,
title: "管理网站【" + siteName + "】CDN-Headers",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -1342,7 +1342,7 @@ function setSiteObjConf(siteName, ruleName, type) {
type: 1,
title: "编辑网站【" + siteName + "】规则【" + ruleName + "】",
area: ['700px', '530px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="divtable">\
@ -1394,7 +1394,7 @@ function siteWafConfig(siteName, type) {
type: 1,
title: "网站配置【" + siteName + "】",
area: ['700px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div id="s_w_c"></div>'
});

@ -22,7 +22,7 @@ from random import Random
TEST_URL = "http://t1.cn/"
def httpGet(url, timeout):
def httpGet(url, timeout=10):
import urllib.request
try:
@ -34,6 +34,19 @@ def httpGet(url, timeout):
return str(e)
def httpGet__UA(url, ua, timeout=10):
import urllib.request
headers = {'user-agent': ua}
try:
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req)
result = response.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpPost(url, data, timeout=10):
"""
发送POST请求
@ -74,15 +87,57 @@ def httpPost(url, data, timeout=10):
def test_Dir():
'''
目录保存
'''
url = TEST_URL + '?t=../etc/passwd'
print("args test start")
httpGet(url, 10)
url_val = httpGet(url, 10)
# print(url_val)
print("args test end")
def test_UA():
'''
user-agent 过滤
'''
url = TEST_URL
print("user-agent test start")
url_val = httpGet__UA(url, 'ApacheBench')
print(url_val)
print("user-agent test end")
def test_POST():
'''
user-agent 过滤
'''
url = TEST_URL
print("POST test start")
url_val = httpPost(url, {'data': "substr($mmsss,0,1)"})
# url_val = httpPost(url, {'data': "123123"})
print(url_val)
print("POST test end")
def test_scan():
'''
目录保存
'''
url = TEST_URL + '/acunetix_wvs_security_test?t=1'
print("scan test start")
url_val = httpGet(url, 10)
print(url_val)
print("scan test end")
def test_start():
test_Dir()
test_UA()
test_POST()
test_scan()
if __name__ == "__main__":
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/op_waf && sh install.sh uninstall 0.1 && sh install.sh install 0.1')
test_start()

@ -1,26 +1,87 @@
local setmetatable = setmetatable
local _M = { _VERSION = '0.01' }
local _M = { _VERSION = '0.02' }
local mt = { __index = _M }
local json = require "cjson"
local ngx_match = ngx.re.find
local debug_mode = false
local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/"
local logdir = waf_root.."/logs/"
local rpath = cpath.."/rule/"
function _M.new(self)
function _M.new(self, cpath, rpath, logdir)
-- ngx.log(ngx.ERR,"read:"..cpath..",rpath:"..rpath)
local opt = {
cpath = cpath,
rpath = rpath,
logdir = logdir,
config = '',
site_config = '',
params = nil
local self = {
waf_root = waf_root,
cpath = cpath,
rpath = rpath,
logdir = logdir,
config = '',
site_config = '',
params = nil
}
local p = setmetatable(opt, mt)
return p
return setmetatable(self, mt)
end
function _M.setDebug(self, mode)
debug_mode = mode
end
-- 调试方式
function _M.D(self, msg)
if not debug_mode then return true end
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = tostring( key)..':'.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
local fp = io.open(waf_root.."/debug.log", "ab")
if fp == nil then
return nil
end
local localtime = os.date("%Y-%m-%d %H:%M:%S")
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end
local function write_file_clear(filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
end
function _M.setConfData( self, config, site_config )
self.config = config
self.site_config = site_config
@ -94,6 +155,10 @@ function _M.compare_ip(self,ips)
end
function _M.to_json(self, msg)
return json.encode(msg)
end
function _M.return_message(self, status, msg)
ngx.header.content_type = "application/json;"
ngx.status = status
@ -136,15 +201,9 @@ function _M.write_file(self, filename, body)
return true
end
function _M.write_file_clear(self, filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
return write_file_clear(filename, body)
end
@ -234,11 +293,21 @@ function _M.read_file(self, name)
end
function _M.read_file_table( self, name )
return self:select_rule(self:read_file('args'))
return self:select_rule(self:read_file(name))
end
local function timer_at_inc_log(premature)
local total_path = cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path)
if not tbody then
return false
end
return write_file_clear(total_path,tbody)
end
function _M.inc_log(self, name, rule)
local server_name = self.params['server_name']
local total_path = self.cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path)
@ -246,7 +315,10 @@ function _M.inc_log(self, name, rule)
tbody = self:read_file_body(total_path)
if not tbody then return false end
end
local total = json.decode(tbody)
-- 开始计算
if not total['sites'] then total['sites'] = {} end
if not total['sites'][server_name] then total['sites'][server_name] = {} end
if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end
@ -256,13 +328,15 @@ function _M.inc_log(self, name, rule)
total['total'] = total['total'] + 1
total['sites'][server_name][name] = total['sites'][server_name][name] + 1
total['rules'][name] = total['rules'][name] + 1
local total_log = json.encode(total)
if not total_log then return false end
ngx.shared.limit:set(total_path,total_log)
if not ngx.shared.limit:get('mw_waf_timeout') then
self:write_file_clear(total_path,total_log)
ngx.shared.limit:set('mw_waf_timeout',1,5)
end
-- 异步执行
ngx.timer.at(1, timer_at_inc_log)
end
@ -294,6 +368,54 @@ end
-- end
function _M.is_ngx_match_orgin(self,rule,match, sign)
if ngx_match(ngx.unescape_uri(match), rule,"isjo") then
error_rule = rule .. ' >> ' .. sign .. ':' .. match
return true
end
return false
end
function _M.ngx_match_string(self, rules, content,sign)
local t = self:is_ngx_match_orgin(rules, content, sign)
if t then
return true
end
return false
end
function _M.is_ngx_match_ua(self, rules, content)
-- ngx.header.content_type = "text/html"
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match_post(self, rules, content)
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2],content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match(self, rules, sbody, rule_name)
if rules == nil or sbody == nil then return false end
if type(sbody) == "string" then
@ -341,6 +463,7 @@ end
function _M.write_log(self, name, rule)
local ip = self.params['ip']
local retry = self.config['retry']['retry']
local retry_time = self.config['retry']['retry_time']

@ -1,47 +1,27 @@
local cpath = "{$WAF_PATH}/"
local rpath = "{$WAF_PATH}/rule/"
local logdir = "{$WAF_ROOT}/logs/"
local json = require "cjson"
local ngx_match = ngx.re.find
local _C = require "common"
local C = _C:new(cpath, rpath, logdir)
local __C = require "common"
local C = __C:new()
local waf_root = "{$WAF_ROOT}"
config = C:read_file_body_decode(cpath .. 'config.json')
local site_config = C:read_file_body_decode(cpath .. 'site.json')
config = C:read_file_body_decode(waf_root.."/waf/"..'config.json')
local site_config = C:read_file_body_decode(waf_root.."/waf/"..'site.json')
C:setConfData(config, site_config)
-- D func
local function D(msg)
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = key..':'..val.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
if not debug_mode then return true end
local fp = io.open(cpath..'debug.log', 'ab')
if fp == nil then
return nil
end
local localtime = os.date("%Y-%m-%d %H:%M:%S")
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"])
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
local args_rules = C:read_file_table('args')
local ip_white_rules = C:read_file('ip_white')
local ip_black_rules = C:read_file('ip_black')
local scan_black_rules = C:read_file('scan_black')
local user_agent_rules = C:read_file('user_agent')
local post_rules = C:read_file('post')
function initParams()
local data = {}
@ -53,13 +33,14 @@ function initParams()
data['uri_request_args'] = ngx.req.get_uri_args()
data['method'] = ngx.req.get_method()
data['request_uri'] = ngx.var.request_uri
data['cookie'] = ngx.var.http_cookie
return data
end
local params = initParams()
C:setParams(params)
C:setDebug(true)
function get_return_state(rstate,rmsg)
result = {}
@ -102,7 +83,7 @@ function save_ip_on(data)
end
end
function remove_btwaf_drop_ip()
function remove_waf_drop_ip()
if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
@ -125,7 +106,7 @@ function remove_btwaf_drop_ip()
return get_return_state(true,uri_request_args['ip'] .. '已解封')
end
function clean_btwaf_drop_ip()
function clean_waf_drop_ip()
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data2=json.decode(ret2)
@ -155,14 +136,6 @@ function min_route()
end
end
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"])
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
local args_rules = C:read_file_table('args')
local ip_white_rules = C:read_file('ip_white')
local ip_black_rules = C:read_file('ip_black')
local scan_black_rules = C:read_file('scan_black')
function waf_args()
if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(args_rules, params['uri_request_args'],'args') then
@ -208,9 +181,9 @@ end
function waf_user_agent()
D("12312")
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
if C:is_ngx_match(user_agent_rules,params['request_header']['user-agent'],'user_agent') then
-- user_agent 过滤
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
if C:is_ngx_match_ua(user_agent_rules,params['request_header']['user-agent']) then
C:write_log('user_agent','regular')
C:return_html(config['user-agent']['status'],user_agent_html)
return true
@ -288,20 +261,25 @@ end
function waf_scan_black()
-- 扫描软件禁止
if not config['scan']['open'] or not C:is_site_config('scan') then return false end
if C:is_ngx_match(scan_black_rules['cookie'],params["request_header"]["cookie"],false) then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
if not params["cookie"] then
if C:ngx_match_string(scan_black_rules['cookie'], tostring(params["cookie"]),'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
end
if C:is_ngx_match(scan_black_rules['args'],params["request_uri"],false) then
if C:ngx_match_string(scan_black_rules['args'], params["request_uri"], 'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
for key,value in pairs(params["request_header"])
do
if C:is_ngx_match(scan_black_rules['header'], key, false) then
if C:ngx_match_string(scan_black_rules['header'], key, 'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
@ -334,7 +312,19 @@ function waf_post()
return false
end
if C:is_ngx_match(post_rules,request_args,'post') then
for key, val in pairs(request_args) do
if type(val) == "table" then
if type(val[1]) == "boolean" then
return false
end
data = table.concat(val, ", ")
else
data = val
end
end
if C:is_ngx_match_post(post_rules,data) then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
return true
@ -367,10 +357,11 @@ function post_data_chekc()
end
if not list_list then return false end
aaa=nil
aaa = nil
for k,v in pairs(request_args)
do
aaa=v
aaa = v
end
if not aaa then return false end
@ -382,7 +373,7 @@ function post_data_chekc()
if not data_len then return false end
if arrlen(data_len) ==0 then return false end
if C:is_ngx_match(post_rules,data_len,'post') then
if C:is_ngx_match_post(post_rules , data_len) then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
return true
@ -601,6 +592,8 @@ function waf()
end
waf_args()
-- 扫描软件禁止
waf_scan_black()
waf_post()

@ -1 +1 @@
[[1,"(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)","关键词过滤1",0],[2,"(ApacheBench)","AB测试",0]]
[[1,"(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)","关键词过滤1",0],[1,"(ApacheBench)","AB测试",0]]
Loading…
Cancel
Save