mirror of https://github.com/midoks/mdserver-web
parent
8578579aeb
commit
1de56778e7
@ -0,0 +1,13 @@ |
|||||||
|
RulePath = "/www/server/panel/vhost/wafconf/" |
||||||
|
attacklog = "on" |
||||||
|
logdir = "/www/wwwlogs/waf/" |
||||||
|
UrlDeny="on" |
||||||
|
Redirect="on" |
||||||
|
CookieMatch="off" |
||||||
|
postMatch="off" |
||||||
|
whiteModule="on" |
||||||
|
black_fileExt={"php","jsp"} |
||||||
|
ipWhitelist={"127.0.0.1"} |
||||||
|
ipBlocklist={"1.0.0.1"} |
||||||
|
CCDeny="off" |
||||||
|
CCrate="300/60" |
@ -0,0 +1,245 @@ |
|||||||
|
require 'config' |
||||||
|
local match = string.match |
||||||
|
local ngxmatch=ngx.re.find |
||||||
|
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 |
||||||
|
|
||||||
|
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() |
||||||
|
if Redirect then |
||||||
|
ngx.header.content_type = "text/html" |
||||||
|
ngx.status = ngx.HTTP_FORBIDDEN |
||||||
|
ngx.say(html) |
||||||
|
ngx.exit(ngx.status) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
function whiteurl() |
||||||
|
if WhiteCheck then |
||||||
|
if wturlrules ~=nil then |
||||||
|
for _,rule in pairs(wturlrules) do |
||||||
|
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 |
||||||
|
return false |
||||||
|
end |
||||||
|
|
||||||
|
function get_boundary() |
||||||
|
local header = get_headers()["content-type"] |
||||||
|
if not header then |
||||||
|
return nil |
||||||
|
end |
||||||
|
|
||||||
|
if type(header) == "table" then |
||||||
|
header = header[1] |
||||||
|
end |
||||||
|
|
||||||
|
local m = match(header, ";%s*boundary=\"([^\"]+)\"") |
||||||
|
if m then |
||||||
|
return m |
||||||
|
end |
||||||
|
|
||||||
|
return match(header, ";%s*boundary=([^\",;]+)") |
||||||
|
end |
||||||
|
|
||||||
|
function whiteip() |
||||||
|
if next(ipWhitelist) ~= nil then |
||||||
|
for _,ip in pairs(ipWhitelist) do |
||||||
|
if getClientIp()==ip then |
||||||
|
return true |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
return false |
||||||
|
end |
||||||
|
|
||||||
|
function blockip() |
||||||
|
if next(ipBlocklist) ~= nil then |
||||||
|
for _,ip in pairs(ipBlocklist) do |
||||||
|
if getClientIp()==ip then |
||||||
|
ngx.exit(444) |
||||||
|
return true |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
return false |
||||||
|
end |
@ -0,0 +1,88 @@ |
|||||||
|
local content_length=tonumber(ngx.req.get_headers()['content-length']) |
||||||
|
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 |
@ -0,0 +1,24 @@ |
|||||||
|
\.\./ |
||||||
|
\:\$ |
||||||
|
\$\{ |
||||||
|
/\*|-- |
||||||
|
\b(or|xor|and)\b.*(=|<|>|'|") |
||||||
|
select.+(from|limit) |
||||||
|
(?:(union(.*?)select)) |
||||||
|
having|load_file |
||||||
|
sleep\((\s*)(\d*)(\s*)\) |
||||||
|
benchmark\((.*)\,(.*)\) |
||||||
|
base64_decode\( |
||||||
|
(?:from\W+information_schema\W) |
||||||
|
(?:(?:current_)user|database|schema|connection_id)\s*\( |
||||||
|
(?:etc\/\W*passwd) |
||||||
|
into(\s+)+(?:dump|out)file\s* |
||||||
|
group\s+by.+\( |
||||||
|
xwork.MethodAccessor |
||||||
|
(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( |
||||||
|
xwork\.MethodAccessor |
||||||
|
(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ |
||||||
|
java\.lang |
||||||
|
\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ |
||||||
|
\<(iframe|script|body|img|layer|div|meta|style|base|object|input) |
||||||
|
(onmouseover|onerror|onload)\= |
@ -0,0 +1 @@ |
|||||||
|
10.0.68.75 |
@ -0,0 +1,20 @@ |
|||||||
|
\.\./ |
||||||
|
\:\$ |
||||||
|
\$\{ |
||||||
|
select.+(from|limit) |
||||||
|
(?:(union(.*?)select)) |
||||||
|
having|rongjitest |
||||||
|
sleep\((\s*)(\d*)(\s*)\) |
||||||
|
benchmark\((.*)\,(.*)\) |
||||||
|
base64_decode\( |
||||||
|
(?:from\W+information_schema\W) |
||||||
|
(?:(?:current_)user|database|schema|connection_id)\s*\( |
||||||
|
(?:etc\/\W*passwd) |
||||||
|
into(\s+)+(?:dump|out)file\s* |
||||||
|
group\s+by.+\( |
||||||
|
xwork.MethodAccessor |
||||||
|
(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( |
||||||
|
xwork\.MethodAccessor |
||||||
|
(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ |
||||||
|
java\.lang |
||||||
|
\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ |
@ -0,0 +1,7 @@ |
|||||||
|
#ip 60/60 1800 |
||||||
|
#ip+uri 60/60 1800 |
||||||
|
#ip+domain+CookieParam:sessionid 60/60 1800 |
||||||
|
#ip+GetParam:userid 60/60 1800 |
||||||
|
#ip+PostParam:userid 60/60 1800 |
||||||
|
#$ip+header:imei 30/60 1800 |
||||||
|
ip+uri 60/60 3600 |
@ -0,0 +1,18 @@ |
|||||||
|
select.+(from|limit) |
||||||
|
(?:(union(.*?)select)) |
||||||
|
\b(or|xor|and)\b.*(=|<|>|'|") |
||||||
|
having|load_file |
||||||
|
sleep\((\s*)(\d*)(\s*)\) |
||||||
|
benchmark\((.*)\,(.*)\) |
||||||
|
base64_decode\( |
||||||
|
(?:from\W+information_schema\W) |
||||||
|
into(\s+)+(?:dump|out)file\s* |
||||||
|
group\s+by.+\( |
||||||
|
xwork.MethodAccessor |
||||||
|
(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( |
||||||
|
xwork\.MethodAccessor |
||||||
|
(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ |
||||||
|
java\.lang |
||||||
|
\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ |
||||||
|
\<(iframe|script|body|img|layer|div|meta|style|base|object|input) |
||||||
|
(onmouseover|onerror|onload)\= |
@ -0,0 +1,39 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<title>网站防火墙</title> |
||||||
|
<style> |
||||||
|
*{margin:0;padding:0;color:#444} |
||||||
|
body{font-size:14px;font-family:"宋体"} |
||||||
|
.main{width:600px;margin:10% auto;} |
||||||
|
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;} |
||||||
|
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px} |
||||||
|
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;} |
||||||
|
.t2{margin-bottom:8px; font-weight:bold} |
||||||
|
ol{margin:0 0 20px 22px;padding:0;} |
||||||
|
ol li{line-height:30px} |
||||||
|
</style> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
<div class="main"> |
||||||
|
<div class="title">网站防火墙</div> |
||||||
|
<div class="content"> |
||||||
|
<p class="t1">您的请求带有不合法参数,已被网站管理员设置拦截!</p> |
||||||
|
<p class="t2">可能原因:</p> |
||||||
|
<ol> |
||||||
|
<li>您提交的内容包含危险的攻击请求</li> |
||||||
|
</ol> |
||||||
|
<p class="t2">如何解决:</p> |
||||||
|
<ol> |
||||||
|
<li>检查提交内容;</li> |
||||||
|
<li>如网站托管,请联系空间提供商;</li> |
||||||
|
<li>普通网站访客,请联系网站管理员;</li> |
||||||
|
<li>这是误报,请联系宝塔 <a href="http://www.bt.cn/bbs" target="_brank">http://www.bt.cn/bbs</a></li> |
||||||
|
</ol> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
||||||
|
|
@ -0,0 +1,9 @@ |
|||||||
|
\.(svn|htaccess|mysql_history|bash_history|git|DS_Store|idea|user\.ini) |
||||||
|
\.(bak|inc|old|mdb|sh|sql|php~|swp|java|class)$ |
||||||
|
(vhost|bbs|host|wwwroot|www|site|root|backup|data|ftp|db|admin|website|web).*\.(rar|sql|zip|tar\.gz|tar) |
||||||
|
(elastic|jmx-console|jmxinvokerservlet) |
||||||
|
java\.lang |
||||||
|
/CSV/ |
||||||
|
/(hack|shell|spy|phpspy)\.php$ |
||||||
|
(manager|host-manager)/html$ |
||||||
|
/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|forumdata|upload|includes|cache|avatar)/(\\w+).(php|jsp) |
@ -0,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|bench| SF/) |
@ -0,0 +1,2 @@ |
|||||||
|
127.0.0.1 |
||||||
|
^192\.168\. |
@ -0,0 +1 @@ |
|||||||
|
^/phpmyadmin_ |
Loading…
Reference in new issue