关于强制性验证优化

pull/436/head
midoks 2 years ago
parent 6eadad5db4
commit 6e9d5a19c0
  1. 137
      plugins/op_waf/index.py
  2. 24
      plugins/op_waf/js/op_waf.js
  3. 67
      plugins/op_waf/waf/config.json
  4. 18
      plugins/op_waf/waf/html/safe_js.html
  5. 27
      plugins/op_waf/waf/lua/init.lua
  6. 2
      plugins/op_waf/waf/lua/init_worker.lua
  7. 4
      plugins/op_waf/waf/lua/waf_common.lua

@ -101,10 +101,11 @@ def pSqliteDb(dbname='logs'):
return conn
def initDomainInfo():
def initDomainInfo(conf_reload=False):
data = []
path_domains = getJsonPath('domains')
if not os.path.exists(path_domains) and not conf_reload:
return True
_list = mw.M('sites').field('id,name,path').where(
'status=?', ('1',)).order('id desc').select()
@ -126,11 +127,15 @@ def initDomainInfo():
mw.writeFile(path_domains, cjson)
def initSiteInfo():
def initSiteInfo(conf_reload=False):
data = []
path_site = getJsonPath('site')
if os.path.exists(path_site) and not conf_reload:
return True
path_domains = getJsonPath('domains')
path_config = getJsonPath('config')
path_site = getJsonPath('site')
config_contents = mw.readFile(path_config)
config_contents = json.loads(config_contents)
@ -140,6 +145,8 @@ def initSiteInfo():
try:
site_contents = mw.readFile(path_site)
if not site_contents:
site_contents = "{}"
except Exception as e:
site_contents = "{}"
@ -196,10 +203,14 @@ def initSiteInfo():
mw.writeFile(path_site, cjson)
def initTotalInfo():
def initTotalInfo(conf_reload=False):
data = []
path_domains = getJsonPath('domains')
path_total = getJsonPath('total')
if os.path.exists(path_total) or not conf_reload:
return True
path_domains = getJsonPath('domains')
domain_contents = mw.readFile(path_domains)
domain_contents = json.loads(domain_contents)
@ -255,6 +266,13 @@ def autoMakeLuaConfSingle(file, conf_reload=False):
listToLuaFile(dst_path, content)
def autoCpImport(file):
path = getPluginDir() + "/waf/" + file + ".json"
dst_path = getServerDir() + "/waf/" + file + ".json"
content = mw.readFile(path)
mw.writeFile(dst_path, content)
def autoMakeLuaImportSingle(file, conf_reload=False):
path = getServerDir() + "/waf/" + file + ".json"
dst_path = getServerDir() + "/waf/conf/waf_" + file + ".lua"
@ -281,7 +299,7 @@ def autoCpHtml(file):
mw.writeFile(dst_path, content)
def autoMakeLuaConf(conf_reload=False):
def autoMakeLuaConf(conf_reload=False, cp_reload=False):
conf_list = ['args', 'cookie', 'ip_black', 'ip_white',
'ipv6_black', 'post', 'scan_black', 'url',
'url_white', 'user_agent']
@ -290,11 +308,13 @@ def autoMakeLuaConf(conf_reload=False):
import_list = ['config', 'site', 'domains']
for x in import_list:
if cp_reload:
autoCpImport(x)
autoMakeLuaImportSingle(x, conf_reload)
html_list = ['get', 'post', 'safe_js', 'user_agent', 'cookie', 'other']
for x in html_list:
if conf_reload:
if cp_reload:
autoCpHtml(x)
autoMakeLuaHtmlSingle(x, conf_reload)
@ -303,30 +323,39 @@ def initDefaultInfo(conf_reload=False):
path = getServerDir()
djson = path + "/waf/domains.json"
default_json = path + "/waf/default.json"
if not os.path.exists(djson) or conf_reload:
content = mw.readFile(djson)
content = json.loads(content)
if os.path.exists(djson) and not conf_reload:
return True
ddata = {}
dlist = []
for i in content:
dlist.append(i["name"])
content = mw.readFile(djson)
content = json.loads(content)
dlist.append('unset')
ddata["list"] = dlist
if len(ddata["list"]) < 1:
ddata["default"] = "unset"
else:
ddata["default"] = dlist[0]
ddata = {}
dlist = []
for i in content:
dlist.append(i["name"])
mw.writeFile(default_json, json.dumps(ddata))
dlist.append('unset')
ddata["list"] = dlist
if len(ddata["list"]) < 1:
ddata["default"] = "unset"
else:
ddata["default"] = dlist[0]
mw.writeFile(default_json, json.dumps(ddata))
def autoMakeConfig(conf_reload=False):
def autoMakeConfig(conf_reload=False, cp_reload=False):
initDomainInfo(conf_reload)
initSiteInfo(conf_reload)
initTotalInfo(conf_reload)
autoMakeLuaConf(conf_reload)
autoMakeLuaConf(conf_reload, cp_reload)
initDefaultInfo(conf_reload)
def setConfRestartWeb():
autoMakeConfig(True, False)
mw.opWeb('stop')
mw.opWeb('start')
def restartWeb():
@ -419,7 +448,6 @@ def initDreplace():
config = path + '/waf/config.json'
content = mw.readFile(config)
content = json.loads(content)
content['reqfile_path'] = path + "/waf/html"
mw.writeFile(config, mw.getJson(content))
@ -432,11 +460,7 @@ def initDreplace():
content = contentReplace(content)
mw.writeFile(waf_conf, content)
initDomainInfo()
initSiteInfo()
initTotalInfo()
autoMakeLuaConf()
initDefaultInfo()
autoMakeConfig()
pSqliteDb()
@ -481,8 +505,7 @@ def reload():
mw.opWeb('stop')
makeOpDstRunLua(True)
autoMakeLuaConf(True)
initDefaultInfo(True)
autoMakeConfig(True, False)
elog = mw.getServerDir() + "/openresty/nginx/logs/error.log"
if os.path.exists(elog):
@ -538,7 +561,8 @@ def addRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', content)
@ -560,7 +584,8 @@ def removeRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', content)
@ -585,7 +610,8 @@ def setRuleState():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', content)
@ -616,7 +642,8 @@ def modifyRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', content)
@ -657,7 +684,8 @@ def addSiteRule():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -693,7 +721,7 @@ def addIpWhite():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -715,7 +743,7 @@ def removeIpWhite():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -752,7 +780,7 @@ def addIpBlack():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -774,7 +802,7 @@ def removeIpBlack():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -793,7 +821,7 @@ def setIpv6Black():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -813,7 +841,7 @@ def delIpv6Black():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -837,7 +865,7 @@ def removeSiteRule():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -858,7 +886,7 @@ def setObjStatus():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -878,13 +906,13 @@ def setRetry():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', [])
def setSafeVerify():
args = getArgs()
data = checkArgs(args, ['auto', 'time', 'cpu'])
data = checkArgs(args, ['auto', 'time', 'cpu', 'mode'])
if not data[0]:
return data[1]
@ -894,6 +922,7 @@ def setSafeVerify():
cobj['safe_verify']['time'] = args['time']
cobj['safe_verify']['cpu'] = int(args['cpu'])
cobj['safe_verify']['mode'] = args['mode']
if args['auto'] == '0':
cobj['safe_verify']['auto'] = False
@ -903,7 +932,7 @@ def setSafeVerify():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', [])
@ -934,7 +963,7 @@ def setCcConf():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', [])
@ -952,7 +981,7 @@ def saveScanRule():
cjson = mw.getJson(args)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!', [])
@ -1046,7 +1075,7 @@ def addSiteCdnHeader():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '添加成功!')
@ -1067,7 +1096,7 @@ def removeSiteCdnHeader():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '删除成功!')
@ -1193,7 +1222,7 @@ def setObjOpen():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')
@ -1223,7 +1252,7 @@ def setSiteObjOpen():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
setConfRestartWeb()
return mw.returnJson(True, '设置成功!')

@ -227,7 +227,7 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
//设置safe_verify规则
function setSafeVerify(auto, cpu, time, siteName) {
function setSafeVerify(auto, cpu, time, mode,siteName) {
var svlayer = layer.open({
type: 1,
title: "设置强制安全验证",
@ -241,7 +241,18 @@ function setSafeVerify(auto, cpu, time, siteName) {
</div>\
<div class="line">\
<span class="tname">通行时间</span>\
<div class="info-r"><input class="bt-input-text" name="time" type="number" value="'+ time + '" /> </div>\
<div class="info-r">\
<input class="bt-input-text" name="time" type="number" value="'+ time + '" /> \
</div>\
</div>\
<div class="line">\
<span class="tname">验证模式</span>\
<div class="info-r">\
<select class="bt-input-text mr5" style="width:200px" name="mode">\
<option value="url" '+(mode=='url'?"selected=selected":"")+'>URL跳转验证</option>\
<option value="local" '+(mode=='local'?"selected=selected":"")+'>本地验证</option>\
</select>\
</div>\
</div>\
<div class="line">\
<span class="tname">开启自动</span>\
@ -249,8 +260,8 @@ function setSafeVerify(auto, cpu, time, siteName) {
<select class="bt-input-text mr5" style="width:80px" name="auto">\
<option value="0" '+(auto==false?"selected=selected":"")+'>关闭</option>\
<option value="1" '+(auto==true?"selected=selected":"")+'>开启</option>\
</select>\
</div>\
</select>\
</div>\
</div>\
<ul class="help-info-text c7 ptb10">\
<li><font style="color:red;">全局设置强制安全验证</font></li>\
@ -266,6 +277,7 @@ function setSafeVerify(auto, cpu, time, siteName) {
siteName: siteName,
cpu: $("input[name='cpu']").val(),
auto: $("select[name='auto']").val(),
mode: $("select[name='mode']").val(),
time: $("input[name='time']").val(),
}
var act = 'set_safe_verify';
@ -459,7 +471,7 @@ function scanRule() {
var tmp = $.parseJSON(data.data);
var rdata = $.parseJSON(tmp.data);
create_l = layer.open({
create_l = ({
type: 1,
title: "常用扫描器过滤规则",
area: '650px',
@ -1036,7 +1048,7 @@ function wafGloabl(){
<input class="btswitch btswitch-ios" id="close_safe_verify" type="checkbox" '+(rdata.safe_verify.open ? 'checked' : '')+'>\
<label class="btswitch-btn" for="close_safe_verify" onclick="setObjOpen(\'safe_verify\')"></label></div>\
</td>\
<td class="text-right"><a class="btlink" onclick="setSafeVerify('+ rdata.safe_verify.auto + ',' + rdata.safe_verify.cpu + ',' + rdata.safe_verify.time + ')">设置</a> | <a class="btlink" href="javascript:;" onclick="onlineEditFile(0,\''+rdata['reqfile_path']+'/safe_js.html\')"></a></td>\
<td class="text-right"><a class="btlink" onclick="setSafeVerify('+ rdata.safe_verify.auto + ',' + rdata.safe_verify.cpu + ',' + rdata.safe_verify.time + ',\'' + rdata.safe_verify.mode + '\')">设置</a> | <a class="btlink" href="javascript:;" onclick="onlineEditFile(0,\''+rdata['reqfile_path']+'/safe_js.html\')"></a></td>\
</tr>\
<tr>\
<td>GET-URI过滤</td>\

@ -1 +1,66 @@
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "过滤常见扫描测试工具的渗透测试", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "过虑CC攻击", "limit": 120, "endtime": 300, "open": true,"cycle": 60}, "safe_verify":{"status": 200,"ps": "强制安全校验", "reqfile": "safe_js.html","open": false,"cpu":50,"auto":true,"time":86400 },"get": {"status": 200, "ps": "过滤uri、uri参数中常见sql注入、xss等攻击", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 200, "ps": "通常用于过滤浏览器、蜘蛛及一些自动扫描器", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 200, "ps": "其它非通用过滤", "reqfile": "other.html"}, "cookie": {"status": 200, "ps": "过滤利用Cookie发起的渗透攻击", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/waf", "post": {"status": 200, "ps": "过滤POST参数中常见sql注入、xss等攻击", "open": true, "reqfile": "post.html"}, "open": true}
{
"reqfile_path": "{$WAF_PATH}/html",
"retry": {
"retry_time": 180,
"is_open_global": 0,
"retry": 6,
"retry_cycle": 60
},
"log": true,
"scan": {
"status": 444,
"ps": "过滤常见扫描测试工具的渗透测试",
"open": true,
"reqfile": ""
},
"cc": {
"status": 444,
"ps": "过虑CC攻击",
"limit": 120,
"endtime": 300,
"open": true,
"cycle": 60
},
"safe_verify": {
"status": 200,
"ps": "强制安全校验",
"reqfile": "safe_js.html",
"open": false,
"mode":"url",
"cpu": 50,
"auto": true,
"time": 86400
},
"get": {
"status": 200,
"ps": "过滤uri、uri参数中常见sql注入、xss等攻击",
"open": true,
"reqfile": "get.html"
},
"log_save": 30,
"user-agent": {
"status": 200,
"ps": "通常用于过滤浏览器、蜘蛛及一些自动扫描器",
"open": true,
"reqfile": "user_agent.html"
},
"other": {
"status": 200,
"ps": "其它非通用过滤",
"reqfile": "other.html"
},
"cookie": {
"status": 200,
"ps": "过滤利用Cookie发起的渗透攻击",
"open": true,
"reqfile": "cookie.html"
},
"logs_path": "/www/wwwlogs/waf",
"post": {
"status": 200,
"ps": "过滤POST参数中常见sql注入、xss等攻击",
"open": true,
"reqfile": "post.html"
},
"open": true
}

@ -27,6 +27,15 @@
<script type="text/javascript">
function getQueryString(name) {
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
let r = window.location.search.substr(1).match(reg);
if (r != null) {
return decodeURIComponent(r[2]);
};
return null;
}
function ajax(type,bool){
var xhr = {};
if(typeof(type)=='undefined'){
@ -135,7 +144,14 @@ var ok = setInterval(function(){
if (data['status'] == 0 && data['msg'] == 'ok'){
document.getElementById('status').innerHTML = 'ok';
setTimeout(function(){
location.reload();
var f = getQueryString('f');
// console.log(f,typeof(f));
if (f && f!=''){
location.href = f;
} else {
location.reload();
}
},500);
} else{
document.getElementById('change').innerHTML = '?';

@ -358,8 +358,31 @@ local function waf_cc_increase()
ngx.exit(200)
end
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
C:return_html(200, cc_html)
if not config['safe_verify']['mode'] then return false end
if config['safe_verify']['mode'] == 'url' then
local page = '/safe_verify_'..cache_token
local request_uri = params['uri']
local to_url = page..'?f='..request_uri
local cache_url_key = cache_token..':url'
local cache_url_val = ngx.shared.waf_limit:get(cache_url_key)
if page == request_uri then
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
return C:return_html(200, cc_html)
end
if not cache_url_val then
ngx.shared.waf_limit:set(cache_url_key, request_uri,30)
return ngx.redirect(to_url)
end
end
if config['safe_verify']['mode'] == 'local' then
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
C:return_html(200, cc_html)
end
end

@ -26,7 +26,7 @@ local function waf_timer_stats_total_log(premature)
WAF_C:timer_stats_total()
end
local waf_clean_expire_data = function(premature)
local function waf_clean_expire_data(premature)
WAF_C:clean_log()
end

@ -122,7 +122,7 @@ end
function _M.initDB(self)
local path = log_dir .. "/waf.db"
db, err = sqlite3.open(path)
local db, err = sqlite3.open(path)
if err then
self:D("initDB err:"..tostring(err))
@ -371,7 +371,7 @@ function _M.return_html(self, status, html)
end
function _M.read_file_body(self, filename)
fp = io.open(filename, 'r')
local fp = io.open(filename, 'r')
if fp == nil then
return nil
end

Loading…
Cancel
Save