commit
							parent
							
								
									b29cb04e6a
								
							
						
					
					
						commit
						3d9ff7687f
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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() | ||||
|  | @ -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> | ||||
| ]] | ||||
|  | @ -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 | ||||
|  | @ -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 | ||||
|  | @ -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,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) | ||||
|  | @ -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,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)\= | ||||
|  | @ -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) | ||||
|  | @ -0,0 +1 @@ | |||
| 127.0.0.1 | ||||
|  | @ -0,0 +1,2 @@ | |||
| \.(js|css)$ | ||||
| \.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ | ||||
		Loading…
	
		Reference in New Issue
	
	 lj2007331@gmail.com
						lj2007331@gmail.com