pull/216/head
midoks 3 years ago
parent 63e6a95553
commit e289037598
  1. 1
      plugins/op_waf/conf/init.sql
  2. 18
      plugins/op_waf/index.html
  3. 87
      plugins/op_waf/index.py
  4. 214
      plugins/op_waf/js/op_waf.js
  5. 6
      plugins/op_waf/t/index.py
  6. 9
      plugins/op_waf/waf/lua/common.lua
  7. 1
      plugins/op_waf/waf/lua/init.lua
  8. 2
      plugins/webstats/js/stats.js

@ -10,6 +10,7 @@ CREATE TABLE IF NOT EXISTS `logs` (
`server_name` TEXT,
`method` TEXT,
`status_code` INTEGER,
`user_agent` TEXT,
`uri` TEXT,
`rule_name` TEXT,
`reason` TEXT

@ -1,4 +1,18 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.cur {
background-color: #20a53a;
color: #fff;
}
/*waf*/
.lib-con-title {
height: 26px;
@ -231,8 +245,8 @@
<p onclick="wafScreen();">首页</p>
<p onclick="wafGloabl();">全局配置</p>
<p onclick="wafSite();">站点配置</p>
<p onclick="wafHistory();">封锁历史</p>
<p onclick="wafLogs();">操作日志</p>
<p onclick="wafLogs();">封锁历史</p>
<p onclick="wafOpLogs();">操作日志</p>
</div>
<!-- lib-con -->
<div class="bt-w-con pd15">

@ -291,6 +291,29 @@ def autoMakeLuaConf():
autoMakeLuaHtmlSingle(x)
def initDefaultInfo():
path = getServerDir()
djson = path + "/waf/domains.json"
default_json = path + "/waf/default.json"
if os.path.exists(djson):
content = mw.readFile(djson)
content = json.loads(content)
ddata = {}
dlist = []
for i in content:
dlist.append(i["name"])
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 initDreplace():
path = getServerDir()
@ -341,6 +364,8 @@ def initDreplace():
initTotalInfo()
autoMakeLuaConf()
initDefaultInfo()
pSqliteDb()
if not mw.isAppleSystem():
@ -881,6 +906,26 @@ def getSiteConfig():
return mw.returnJson(True, 'ok!', content)
def getSiteListData():
path = getServerDir() + "/waf/default.json"
data = mw.readFile(path)
return json.loads(data)
def setDefaultSite(name):
path = getServerDir() + "/waf/default.json"
data = mw.readFile(path)
data = json.loads(data)
data['default'] = name
mw.writeFile(path, json.dumps(data))
return mw.returnJson(True, 'OK')
def getDefaultSite():
data = getSiteListData()
return mw.returnJson(True, 'OK', data)
def getSiteConfigByName():
args = getArgs()
data = checkArgs(args, ['siteName'])
@ -963,24 +1008,38 @@ def importData():
def getLogsList():
args = getArgs()
data = checkArgs(args, ['siteName'])
data = checkArgs(args, ['site', 'page', 'page_size', 'tojs'])
if not data[0]:
return data[1]
data = []
path = getServerDir() + '/logs'
page = int(args['page'])
page_size = int(args['page_size'])
domain = args['site']
tojs = args['tojs']
if not os.path.exists(path):
return mw.returnJson(False, '还未生成!', [])
conn = pSqliteDb('logs')
field = 'time,ip,domain,server_name,method,uri,user_agent,rule_name,reason'
limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
condition = ''
conn = conn.field(field)
conn = conn.where("1=1", ()).where("domain=?", (domain,))
clist = conn.limit(limit).order('time desc').inquiry()
count_key = "count(*) as num"
count = conn.field(count_key).limit('').order('').inquiry()
# print(count)
count = count[0][count_key]
files = os.listdir(path)
for f in files:
if f == '.DS_Store':
continue
f = f.split('_')
if f[0] == args['siteName']:
fl = f[1].split('.')
data.append(fl[0])
data = {}
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = tojs
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.returnJson(True, 'ok!', data)
@ -1142,6 +1201,8 @@ if __name__ == "__main__":
print(saveScanRule())
elif func == 'get_site_config':
print(getSiteConfig())
elif func == 'get_default_site':
print(getDefaultSite())
elif func == 'get_site_config_byname':
print(getSiteConfigByName())
elif func == 'add_site_cdn_header':

@ -1611,7 +1611,6 @@ function siteWafConfig(siteName, type) {
function wafSite(){
owPost('get_site_config', {}, function(data){
var tmp = $.parseJSON(data.data);
var rdata = $.parseJSON(tmp.data);
@ -1621,24 +1620,12 @@ function wafSite(){
i += 1;
tbody += '<tr>\
<td><a onclick="siteWafConfig(\''+ k + '\')" class="sitename btlink" title="' + k + '">' + k + '</a></td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span>\
</td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span></td>\
<td>\
<div class="ssh-item" style="margin-left:0">\
<input class="btswitch btswitch-ios" id="closeget_'+ i + '" type="checkbox" ' + (v.open ? 'checked' : '') + '>\
@ -1646,7 +1633,7 @@ function wafSite(){
</div>\
</td>\
<td class="text-right"><a onclick="siteWafLog(\''+ k + '\')" class="btlink ' + (v.log_size > 0 ? 'dot' : '') + '">日志</a> | <a onclick="siteWafConfig(\'' + k + '\')" class="btlink"></a></td>\
</tr>'
</tr>';
});
var con = '<div class="lib-box">\
@ -1680,24 +1667,181 @@ function wafSite(){
function wafHistory(){
var con = '<button class="btn btn-success btn-sm" onclick="UncoverAll()">解封所有</button>';
con += '<div class="divtable mt10">\
<table class="table table-hover waftable" style="color:#fff;">\
<thead><tr><th width="18%">开始时间</th>\
<th width="44%">IP</th>\
<th width="10%">站点</th>\
<th width="10%">封锁原因</th>\
<th width="10%">封锁时长</th>\
<th style="text-align: center;" width="10%">状态</th>\
</thead>\
</table>\
</div>';
$(".soft-man-con").html(con);
}
function wafLogRequest(page){
var args = {};
args['page'] = page;
args['page_size'] = 10;
args['site'] = $('select[name="site"]').val();
var query_date = 'today';
if ($('#time_choose').attr("data-name") != ''){
query_date = $('#time_choose').attr("data-name");
} else {
query_date = $('#search_time button.cur').attr("data-name");
}
args['query_date'] = query_date;
args['tojs'] = 'wafLogRequest';
owPost('get_logs_list', args, function(rdata){
var rdata = $.parseJSON(rdata.data);
var list = '';
var data = rdata.data.data;
if (data.length > 0){
for(i in data){
list += '<tr>';
list += '<td><span class="overflow_hide" style="width:112px;">' + getLocalTime(data[i]['time'])+'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['domain'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:60px;">' + data[i]['ip'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['uri'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['rule_name'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:200px;">' + data[i]['reason'] +'</span></td>';
list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>';
list += '</tr>';
}
} else{
list += '<tr><td colspan="8" style="text-align:center;">封锁日志为空</td></tr>';
}
var table = '<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead><tr>\
<th>时间</th>\
<th>域名</th>\
<th>IP</th>\
<th>URI</th>\
<th>规则名</th>\
<th>原因</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
'+ list +'\
</tbody></table>\
</div>\
<div id="wsPage" class="dataTables_paginate paging_bootstrap page"></div>';
$('#ws_table').html(table);
$('#wsPage').html(rdata.data.page);
$(".tablescroll .details").click(function(){
var index = $(this).attr('data-id');
var res = data[index];
var ip = res.ip;
var time = getLocalTime(res.time);
layer.open({
type: 1,
title: "【"+time + "】详情",
area: '600px',
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
<tbody><tr><th>时间</th><td>'+ time + '</td><th>IP</th><td><a class="btlink" href="javascript:add_log_ip_black(\'' + escapeHTML(ip) + '\')" title="">' + escapeHTML(ip) + '</a></td></tr><tr><th></th><td>' + escapeHTML(res.method) + '</td><th></th><td>' + escapeHTML(res.rule_name) + '</td></tr></tbody></table>\
<div><b style="margin-left:10px">URI地址</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.uri) + '</div></div>\
<div><b style="margin-left:10px">User-Agent</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.user_agent) + '</div></div>\
<div><b style="margin-left:10px">过滤规则</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.rule_name) + '</div></div>\
<div><b style="margin-left:10px">Reason</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.reason) + '</div></div>\
</div>'
})
});
});
}
function wafLogs(){
var randstr = getRandomString(10);
var html = '<div>\
<div style="padding-bottom:10px;">\
<span>网站: </span>\
<select class="bt-input-text" name="site" style="margin-left:4px;width:100px;">\
<option value="unset">未设置</option>\
</select>\
<span style="margin-left:10px">时间: </span>\
<div class="input-group" style="margin-left:10px;width:350px;display: inline-table;vertical-align: top;">\
<div id="search_time" class="input-group-btn btn-group-sm">\
<button data-name="today" type="button" class="btn btn-default">今日</button>\
<button data-name="yesterday" type="button" class="btn btn-default">昨日</button>\
<button data-name="l7" type="button" class="btn btn-default">近7天</button>\
<button data-name="l30" type="button" class="btn btn-default">近30天</button>\
</div>\
<span class="last-span"><input data-name="" type="text" id="time_choose" lay-key="1000001_'+randstr+'" class="form-control btn-group-sm" autocomplete="off" placeholder="自定义时间" style="display: inline-block;font-size: 12px;padding: 0 10px;height:30px;width: 200px;"></span>\
</div>\
</div>\
<div class="divtable mtb10" id="ws_table"></div>\
</div>';
$(".soft-man-con").html(html);
// wafLogRequest(1);
//日期范围
laydate.render({
elem: '#time_choose',
value:'',
range:true,
done:function(value, startDate, endDate){
if(!value){
return false;
}
$('#search_time button').each(function(){
$(this).removeClass('cur');
});
var timeA = value.split('-');
var start = $.trim(timeA[0]+'-'+timeA[1]+'-'+timeA[2])
var end = $.trim(timeA[3]+'-'+timeA[4]+'-'+timeA[5])
query_txt = toUnixTime(start + " 00:00:00") + "-"+ toUnixTime(end + " 00:00:00")
$('#time_choose').attr("data-name",query_txt);
$('#time_choose').addClass("cur");
wsTableErrorLogRequest(1);
},
});
$('#search_time button:eq(0)').addClass('cur');
$('#search_time button').click(function(){
$('#search_time button').each(function(){
if ($(this).hasClass('cur')){
$(this).removeClass('cur');
}
});
$('#time_choose').attr("data-name",'');
$('#time_choose').removeClass("cur");
$(this).addClass('cur');
wafLogRequest(1);
});
owPost('get_default_site',{},function(rdata){
$('select[name="site"]').html('');
var rdata = $.parseJSON(rdata.data);
var rdata = rdata.data;
var default_site = rdata["default"];
var select = '';
for (var i = 0; i < rdata["list"].length; i++) {
if (default_site == rdata["list"][i]){
select += '<option value="'+rdata["list"][i]+'" selected>'+rdata["list"][i]+'</option>';
} else{
select += '<option value="'+rdata["list"][i]+'">'+rdata["list"][i]+'</option>';
}
}
$('select[name="site"]').html(select);
wafLogRequest(1);
$('select[name="site"]').change(function(){
wafLogRequest(1);
});
});
}
function wafOpLogs(){
var con = '<div class="divtable">\
<table class="table table-hover waftable" style="color:#fff;">\
<thead><tr><th width="18%">名称</th>\

@ -164,7 +164,7 @@ def test_scan():
'''
目录保存
'''
url = TEST_URL + '/acunetix_wvs_security_test?t=1'
url = TEST_URL + 'acunetix_wvs_security_test?t=1'
print("scan test start")
url_val = httpGet(url, 10)
print(url_val)
@ -214,8 +214,8 @@ def test_start():
# test_UA()
# test_UA_for(1000)
# test_POST()
# test_scan()
test_CC()
test_scan()
# test_CC()
# test_url_ext()
# test_cdn()

@ -60,13 +60,13 @@ function _M.initDB(self)
db:exec([[PRAGMA journal_size_limit = 1073741824]])
self.db = db
return self.db
return db
end
function _M.log(self, args, rule_name, reason)
local local_db = self:initDB()
local stmt2 = local_db:prepare[[INSERT INTO logs(time, ip, domain, server_name, method, status_code, uri, rule_name, reason)
VALUES(:time, :ip, :domain, :server_name, :method, :status_code, :uri, :rule_name, :reason)]]
local stmt2 = local_db:prepare[[INSERT INTO logs(time, ip, domain, server_name, method, status_code, uri, user_agent, rule_name, reason)
VALUES(:time, :ip, :domain, :server_name, :method, :status_code, :uri, :user_agent, :rule_name, :reason)]]
local_db:exec([[BEGIN TRANSACTION]])
@ -77,6 +77,7 @@ function _M.log(self, args, rule_name, reason)
server_name=args["server_name"],
method=args["method"],
status_code=args["status_code"],
user_agent=args["user_agent"],
uri=args["request_uri"],
rule_name=rule_name,
reason=reason
@ -84,12 +85,12 @@ function _M.log(self, args, rule_name, reason)
local res, err = stmt2:step()
-- self:D("LOG[1]:"..tostring(res)..":"..tostring(err))
if tostring(res) == "5" then
self.D("waf the step database connection is busy, so it will be stored later.")
return false
end
stmt2:reset()
local res, err = local_db:execute([[COMMIT]])
-- self:D("LOG[2]:"..tostring(res)..":"..tostring(err))
if local_db and local_db:isopen() then

@ -45,6 +45,7 @@ local function initParams()
data['method'] = ngx.req.get_method()
data['request_uri'] = ngx.var.request_uri
data['status_code'] = ngx.status
data['user_agent'] = data['request_header']['user-agent']
data['cookie'] = ngx.var.http_cookie
data['time'] = ngx.time()
return data

@ -2110,7 +2110,7 @@ laydate.render({
$(this).removeClass('cur');
});
var timeA = value.split('-')
var timeA = value.split('-');
var start = $.trim(timeA[0]+'-'+timeA[1]+'-'+timeA[2])
var end = $.trim(timeA[3]+'-'+timeA[4]+'-'+timeA[5])
query_txt = toUnixTime(start + " 00:00:00") + "-"+ toUnixTime(end + " 00:00:00")

Loading…
Cancel
Save