pull/109/head
Mr Chen 6 years ago
parent 5a52ed41ad
commit 34f8ef702d
  1. 4
      plugins/op_waf/index.py
  2. 30
      plugins/op_waf/waf/lua/common.lua
  3. 283
      plugins/op_waf/waf/lua/init.lua
  4. 89
      plugins/op_waf/waf/lua/waf.lua

@ -135,10 +135,14 @@ def stop():
def restart(): def restart():
stop()
start()
return 'ok' return 'ok'
def reload(): def reload():
stop()
start()
return 'ok' return 'ok'
def getJsonPath(name): def getJsonPath(name):

@ -0,0 +1,30 @@
function return_message(status,msg)
ngx.header.content_type = "application/json;"
ngx.status = status
ngx.say(json.encode(msg))
ngx.exit(status)
end
function return_html(status,html)
ngx.header.content_type = "text/html"
ngx.status = status
ngx.say(html)
ngx.exit(status)
end
function read_file_body(filename)
fp = io.open(filename,'r')
if fp == nil then
return nil
end
fbody = fp:read("*a")
fp:close()
if fbody == '' then
return nil
end
return fbody
end

@ -1,261 +1,52 @@
RulePath = "{$WAF_PATH}/wafconf" local cpath = "{$WAF_PATH}/"
attacklog = "on" local logdir = "{$ROOT_PATH}/wwwlogs/waf/"
logdir = "{$ROOT_PATH}/wwwlogs/waf/" local json = require "cjson"
UrlDeny="on"
Redirect="on"
CookieMatch="off"
postMatch="off"
whiteModule="on"
black_fileExt={"php","jsp"}
ipWhitelist={"127.0.0.2"}
ipBlocklist={"1.0.0.1"}
CCDeny="off"
CCrate="300/60"
function return_message(status,msg)
ngx.header.content_type = "application/json;"
require 'config' ngx.status = status
local match = string.match ngx.say(json.encode(msg))
local ngxmatch=ngx.re.find ngx.exit(status)
local unescape=ngx.unescape_uri
local get_headers = ngx.req.get_headers
local optionIsOn = function (options) return options == "on" and true or false end
logpath = logdir
rulepath = RulePath
UrlDeny = optionIsOn(UrlDeny)
PostCheck = optionIsOn(postMatch)
CookieCheck = optionIsOn(cookieMatch)
WhiteCheck = optionIsOn(whiteModule)
PathInfoFix = optionIsOn(PathInfoFix)
attacklog = optionIsOn(attacklog)
CCDeny = optionIsOn(CCDeny)
Redirect=optionIsOn(Redirect)
function getClientIp()
IP = ngx.var.remote_addr
if IP == nil then
IP = "unknown"
end
return IP
end
function write(logfile,msg)
local fd = io.open(logfile,"ab")
if fd == nil then return end
fd:write(msg)
fd:flush()
fd:close()
end
function log(method,url,data,ruletag)
if attacklog then
local realIp = getClientIp()
local ua = ngx.var.http_user_agent
local servername=ngx.var.server_name
local time=ngx.localtime()
if ua then
line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..ruletag.."\"\n"
else
line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n"
end
local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log"
write(filename,line)
end
end
------------------------------------规则读取函数-------------------------------------------------------------------
function read_rule(var)
file = io.open(rulepath..'/'..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 end
urlrules=read_rule('url')
argsrules=read_rule('args')
uarules=read_rule('user-agent')
wturlrules=read_rule('whiteurl')
postrules=read_rule('post')
ckrules=read_rule('cookie')
html=read_rule('returnhtml')
function say_html() function return_html(status,html)
if Redirect then ngx.header.content_type = "text/html"
ngx.header.content_type = "text/html" ngx.status = status
ngx.status = ngx.HTTP_FORBIDDEN ngx.say(html)
ngx.say(html) ngx.exit(status)
ngx.exit(ngx.status)
end
end end
function whiteurl() function read_file_body(filename)
if WhiteCheck then fp = io.open(filename,'r')
if wturlrules ~=nil then if fp == nil then
for _,rule in pairs(wturlrules) do return nil
if ngxmatch(ngx.var.uri,rule,"isjo") then
return true
end
end
end
end
return false
end
function fileExtCheck(ext)
local items = Set(black_fileExt)
ext=string.lower(ext)
if ext then
for rule in pairs(items) do
if ngx.re.match(ext,rule,"isjo") then
log('POST',ngx.var.request_uri,"-","file attack with ext "..ext)
say_html()
end
end
end
return false
end
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
function args()
for _,rule in pairs(argsrules) do
local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
if type(val)=='table' then
local t={}
for k,v in pairs(val) do
if v == true then
v=""
end
table.insert(t,v)
end
data=table.concat(t, " ")
else
data=val
end
if data and type(data) ~= "boolean" and rule ~="" and ngxmatch(unescape(data),rule,"isjo") then
log('GET',ngx.var.request_uri,"-",rule)
say_html()
return true
end
end
end
return false
end
function url()
if UrlDeny then
for _,rule in pairs(urlrules) do
if rule ~="" and ngxmatch(ngx.var.request_uri,rule,"isjo") then
log('GET',ngx.var.request_uri,"-",rule)
say_html()
return true
end
end
end
return false
end
function ua()
local ua = ngx.var.http_user_agent
if ua ~= nil then
for _,rule in pairs(uarules) do
if rule ~="" and ngxmatch(ua,rule,"isjo") then
log('UA',ngx.var.request_uri,"-",rule)
say_html()
return true
end
end
end
return false
end
function body(data)
for _,rule in pairs(postrules) do
if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then
log('POST',ngx.var.request_uri,data,rule)
say_html()
return true
end
end
return false
end
function cookie()
local ck = ngx.var.http_cookie
if CookieCheck and ck then
for _,rule in pairs(ckrules) do
if rule ~="" and ngxmatch(ck,rule,"isjo") then
log('Cookie',ngx.var.request_uri,"-",rule)
say_html()
return true
end
end
end
return false
end
function denycc()
if CCDeny then
local uri=ngx.var.uri
CCcount=tonumber(string.match(CCrate,'(.*)/'))
CCseconds=tonumber(string.match(CCrate,'/(.*)'))
local token = getClientIp()..uri
local limit = ngx.shared.limit
local req,_=limit:get(token)
if req then
if req > CCcount then
ngx.exit(444)
return true
else
limit:incr(token,1)
end
else
limit:set(token,1,CCseconds)
end
end end
return false fbody = fp:read("*a")
end fp:close()
if fbody == '' then
function get_boundary()
local header = get_headers()["content-type"]
if not header then
return nil return nil
end end
return fbody
end
if type(header) == "table" then
header = header[1]
end
local m = match(header, ";%s*boundary=\"([^\"]+)\"") -- local config = read_file_body(cpath .. 'config.json')
if m then local config = json.decode(read_file_body(cpath .. 'config.json'))
return m -- local site_config = json.decode(read_file_body(cpath .. 'site.json'))
end
return match(header, ";%s*boundary=([^\",;]+)")
end
function whiteip() -- function args()
if next(ipWhitelist) ~= nil then -- if not config['get']['open'] or not is_site_config('get') then return false end
for _,ip in pairs(ipWhitelist) do -- if is_ngx_match(args_rules,uri_request_args,'args') then
if getClientIp()==ip then -- write_log('args','regular')
return true -- return_html(config['get']['status'],get_html)
end -- return true
end -- end
end -- return false
return false -- end
end
function blockip() function waf()
if next(ipBlocklist) ~= nil then -- return_html(200,cpath .. 'config.json')
for _,ip in pairs(ipBlocklist) do return_message(200, config)
if getClientIp()==ip then
ngx.exit(444)
return true
end
end
end
return false
end end

@ -1,88 +1 @@
local content_length=tonumber(ngx.req.get_headers()['content-length']) waf()
local method=ngx.req.get_method()
local ngxmatch=ngx.re.match
if whiteip() then
elseif blockip() then
elseif denycc() then
elseif ngx.var.http_Acunetix_Aspect then
ngx.exit(444)
elseif ngx.var.http_X_Scan_Memo then
ngx.exit(444)
elseif whiteurl() then
elseif ua() then
elseif url() then
elseif args() then
elseif cookie() then
elseif PostCheck then
if method=="POST" then
local boundary = get_boundary()
if boundary then
local len = string.len
local sock, err = ngx.req.socket()
if not sock then
return
end
ngx.req.init_body(128 * 1024)
sock:settimeout(0)
local content_length = nil
content_length=tonumber(ngx.req.get_headers()['content-length'])
local chunk_size = 4096
if content_length < chunk_size then
chunk_size = content_length
end
local size = 0
while size < content_length do
local data, err, partial = sock:receive(chunk_size)
data = data or partial
if not data then
return
end
ngx.req.append_body(data)
if body(data) then
return true
end
size = size + len(data)
local m = ngxmatch(data,[[Content-Disposition: form-data;(.+)filename="(.+)\\.(.*)"]],'ijo')
if m then
fileExtCheck(m[3])
filetranslate = true
else
if ngxmatch(data,"Content-Disposition:",'isjo') then
filetranslate = false
end
if filetranslate==false then
if body(data) then
return true
end
end
end
local less = content_length - size
if less < chunk_size then
chunk_size = less
end
end
ngx.req.finish_body()
else
ngx.req.read_body()
local args = ngx.req.get_post_args()
if not args then
return
end
for key, val in pairs(args) do
if type(val) == "table" then
if type(val[1]) == "boolean" then
return
end
data=table.concat(val, ", ")
else
data=val
end
if data and type(data) ~= "boolean" and body(data) then
body(key)
end
end
end
end
else
return
end
Loading…
Cancel
Save