pull/4/head
lj2007331@gmail.com 2018-06-24 20:16:03 +08:00
parent b29cb04e6a
commit 3d9ff7687f
13 changed files with 414 additions and 2 deletions

View File

@ -23,6 +23,6 @@ sed -i "s@^nginx_modules_options=.*@nginx_modules_options='--add-module=../lua-n
```
### Copyright
完全copy以下项目
完全copy以下项目:<br />
https://github.com/loveshell/ngx_lua_waf<br />
https://github.com/unixhot/waf
https://github.com/loveshell/ngx_lua_waf

18
access.lua Normal file
View File

@ -0,0 +1,18 @@
require 'init'
function waf_main()
if black_ip_check() then
elseif white_ip_check() then
elseif white_url_check() then
elseif user_agent_attack_check() then
elseif cc_attack_check() then
elseif cookie_attack_check() then
elseif url_attack_check() then
elseif url_args_attack_check() then
--elseif post_attack_check() then
else
return
end
end
waf_main()

60
config.lua Normal file
View File

@ -0,0 +1,60 @@
--WAF config file,enable = "on",disable = "off"
--waf status
config_waf_enable = "on"
--log dir
config_log_dir = "/data/wwwlogs"
--rule setting
config_rule_dir = "/usr/local/nginx/conf/waf/wafconf"
--enable/disable white url
config_white_url_check = "on"
--enable/disable white ip
config_white_ip_check = "on"
--enable/disable block ip
config_black_ip_check = "on"
--enable/disable url filtering
config_url_check = "on"
--enalbe/disable url args filtering
config_url_args_check = "on"
--enable/disable user agent filtering
config_user_agent_check = "on"
--enable/disable cookie deny filtering
config_cookie_check = "on"
--enable/disable cc filtering
config_cc_check = "on"
--cc rate the xxx of xxx seconds
config_cc_rate = "20/60"
--enable/disable post filtering
config_post_check = "on"
--config waf output redirect/html
config_waf_output = "html"
--if config_waf_output ,setting url
config_waf_redirect_url = "/captcha"
config_output_html=[[
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title></title>
<style>
p {
line-height:20px;
}
ul{ list-style-type:none;}
li{ list-style-type:none;}
</style>
</head>
<body style=" padding:0; margin:0; font:14px/1.5 Microsoft Yahei, 宋体,sans-serif; color:#555;">
<div style="margin: 0 auto; width:1000px; padding-top:70px; overflow:hidden;">
<div style="width:600px; float:left;">
<div style=" height:40px; line-height:40px; color:#fff; font-size:16px; overflow:hidden; background:#6bb3f6; padding-left:20px;"> </div>
<div style="border:1px dashed #cdcece; border-top:none; font-size:14px; background:#fff; color:#555; line-height:24px; height:220px; padding:20px 20px 0 20px; overflow-y:auto;background:#f3f7f9;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; color:#fc4f03;"></span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:0px;"></p>
<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1</li>
<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2</li>
<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3访</li></ul>
</div>
</div>
</div>
</body></html>
]]

178
init.lua Normal file
View File

@ -0,0 +1,178 @@
--WAF Action
require 'config'
require 'lib'
--args
local rulematch = ngx.re.find
local unescape = ngx.unescape_uri
--allow white ip
function white_ip_check()
if config_white_ip_check == "on" then
local IP_WHITE_RULE = get_rule('whiteip')
local WHITE_IP = get_client_ip()
if IP_WHITE_RULE ~= nil then
for _,rule in pairs(IP_WHITE_RULE) do
if rule ~= "" and rulematch(WHITE_IP,rule,"jo") then
log_record('White_IP',ngx.var_request_uri,"_","_")
return true
end
end
end
end
end
--deny black ip
function black_ip_check()
if config_black_ip_check == "on" then
local IP_BLACK_RULE = get_rule('blackip')
local BLACK_IP = get_client_ip()
if IP_BLACK_RULE ~= nil then
for _,rule in pairs(IP_BLACK_RULE) do
if rule ~= "" and rulematch(BLACK_IP,rule,"jo") then
log_record('BlackList_IP',ngx.var_request_uri,"_","_")
if config_waf_enable == "on" then
ngx.exit(403)
return true
end
end
end
end
end
end
--allow white url
function white_url_check()
if config_white_url_check == "on" then
local URL_WHITE_RULES = get_rule('whiteurl')
local REQ_URI = ngx.var.request_uri
if URL_WHITE_RULES ~= nil then
for _,rule in pairs(URL_WHITE_RULES) do
if rule ~= "" and rulematch(REQ_URI,rule,"jo") then
return true
end
end
end
end
end
--deny cc attack
function cc_attack_check()
if config_cc_check == "on" then
local USER_AGENT = get_user_agent()
local ATTACK_URL = ngx.var.host .. ngx.var.request_uri
local CC_TOKEN = get_client_ip() .. "." .. ngx.md5(ATTACK_URL .. USER_AGENT)
local limit = ngx.shared.limit
local CCcount=tonumber(string.match(config_cc_rate,'(.*)/'))
local CCseconds=tonumber(string.match(config_cc_rate,'/(.*)'))
local req,_ = limit:get(CC_TOKEN)
if req then
if req > CCcount then
log_record('CC_Attack',ngx.var.request_uri,"-","-")
if config_waf_enable == "on" then
waf_output()
ngx.exit(403)
end
else
limit:incr(CC_TOKEN,1)
end
else
limit:set(CC_TOKEN,1,CCseconds)
end
end
return false
end
--deny cookie
function cookie_attack_check()
if config_cookie_check == "on" then
local COOKIE_RULES = get_rule('cookie')
local USER_COOKIE = ngx.var.http_cookie
if USER_COOKIE ~= nil then
for _,rule in pairs(COOKIE_RULES) do
if rule ~="" and rulematch(USER_COOKIE,rule,"jo") then
log_record('Deny_Cookie',ngx.var.request_uri,"-",rule)
if config_waf_enable == "on" then
waf_output()
return true
end
end
end
end
end
return false
end
--deny url
function url_attack_check()
if config_url_check == "on" then
local URL_RULES = get_rule('blackurl')
local REQ_URI = ngx.var.request_uri
for _,rule in pairs(URL_RULES) do
if rule ~="" and rulematch(REQ_URI,rule,"jo") then
log_record('Deny_URL',REQ_URI,"-",rule)
if config_waf_enable == "on" then
waf_output()
return true
end
end
end
end
return false
end
--deny url args
function url_args_attack_check()
if config_url_args_check == "on" then
local ARGS_RULES = get_rule('args')
for _,rule in pairs(ARGS_RULES) do
local REQ_ARGS = ngx.req.get_uri_args()
for key, val in pairs(REQ_ARGS) do
if type(val) == 'table' then
ARGS_DATA = table.concat(val, " ")
else
ARGS_DATA = val
end
if ARGS_DATA and type(ARGS_DATA) ~= "boolean" and rule ~="" and rulematch(unescape(ARGS_DATA),rule,"jo") then
log_record('Deny_URL_Args',ngx.var.request_uri,"-",rule)
if config_waf_enable == "on" then
waf_output()
return true
end
end
end
end
end
return false
end
--deny user agent
function user_agent_attack_check()
if config_user_agent_check == "on" then
local USER_AGENT_RULES = get_rule('useragent')
local USER_AGENT = ngx.var.http_user_agent
if USER_AGENT ~= nil then
for _,rule in pairs(USER_AGENT_RULES) do
if rule ~="" and rulematch(USER_AGENT,rule,"jo") then
log_record('Deny_USER_AGENT',ngx.var.request_uri,"-",rule)
if config_waf_enable == "on" then
waf_output()
return true
end
end
end
end
end
return false
end
--deny post
function post_attack_check()
if config_post_check == "on" then
local POST_RULES = get_rule('post')
for _,rule in pairs(ARGS_RULES) do
local POST_ARGS = ngx.req.get_post_args()
end
return true
end
return false
end

84
lib.lua Normal file
View File

@ -0,0 +1,84 @@
--waf core lib
require 'config'
--Get the client IP
function get_client_ip()
CLIENT_IP = ngx.req.get_headers()["X_real_ip"]
if CLIENT_IP == nil then
CLIENT_IP = ngx.req.get_headers()["X_Forwarded_For"]
end
if CLIENT_IP == nil then
CLIENT_IP = ngx.var.remote_addr
end
if CLIENT_IP == nil then
CLIENT_IP = "unknown"
end
return CLIENT_IP
end
--Get the client user agent
function get_user_agent()
USER_AGENT = ngx.var.http_user_agent
if USER_AGENT == nil then
USER_AGENT = "unknown"
end
return USER_AGENT
end
--Get WAF rule
function get_rule(rulefilename)
local io = require 'io'
local RULE_PATH = config_rule_dir
local RULE_FILE = io.open(RULE_PATH..'/'..rulefilename,"r")
if RULE_FILE == nil then
return
end
RULE_TABLE = {}
for line in RULE_FILE:lines() do
table.insert(RULE_TABLE,line)
end
RULE_FILE:close()
return(RULE_TABLE)
end
--WAF log record for json,(use logstash codec => json)
function log_record(method,url,data,ruletag)
local cjson = require("cjson")
local io = require 'io'
local LOG_PATH = config_log_dir
local CLIENT_IP = get_client_ip()
local USER_AGENT = get_user_agent()
local SERVER_NAME = ngx.var.host
local LOCAL_TIME = ngx.localtime()
local log_json_obj = {
client_ip = CLIENT_IP,
local_time = LOCAL_TIME,
server_name = SERVER_NAME,
req_url = url,
attack_method = method,
req_data = data,
rule_tag = ruletag,
user_agent = USER_AGENT,
}
local LOG_LINE = cjson.encode(log_json_obj)
local LOG_NAME = LOG_PATH..'/'..ngx.today().."_sec.log"
local file = io.open(LOG_NAME,"a")
if file == nil then
return
end
file:write(LOG_LINE.."\n")
file:flush()
file:close()
end
--WAF return
function waf_output()
if config_waf_output == "redirect" then
ngx.redirect(config_waf_redirect_url, 301)
else
ngx.header.content_type = "text/html"
ngx.status = ngx.HTTP_FORBIDDEN
ngx.say(config_output_html)
ngx.exit(ngx.status)
end
end

22
wafconf/args Normal file
View File

@ -0,0 +1,22 @@
\.\./
\:\$
\$\{
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)\[
\<(iframe|script|body|img|layer|div|meta|style|base|object|input)
(onmouseover|onerror|onload)\=

0
wafconf/blackip Normal file
View File

6
wafconf/blackurl Normal file
View File

@ -0,0 +1,6 @@
\.(htaccess|bash_history)
\.(bak|inc|old|mdb|sql|backup|java|class|tgz|gz|tar|zip)$
(phpmyadmin|jmx-console|admin-console|jmxinvokerservlet)
java\.lang
\.svn\/
/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\\w+).(php|jsp)

20
wafconf/cookie Normal file
View File

@ -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)\[

20
wafconf/post Normal file
View File

@ -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)\[
\<(iframe|script|body|img|layer|div|meta|style|base|object|input)
(onmouseover|onerror|onload)\=

1
wafconf/useragent Normal file
View File

@ -0,0 +1 @@
(HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench)

1
wafconf/whiteip Normal file
View File

@ -0,0 +1 @@
127.0.0.1

2
wafconf/whiteurl Normal file
View File

@ -0,0 +1,2 @@
\.(js|css)$
\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$