From 64f91d6bf17bb2d07448b7967abebdb0604ae8b9 Mon Sep 17 00:00:00 2001 From: carfiedli <1073490398@qq.com> Date: Mon, 16 Dec 2024 21:51:57 +0800 Subject: [PATCH] base rule check --- access_all.lua | 14 +++++++- conf_json/base.json | 4 +++ init.lua | 27 ++++++++++++++ waf_rule_check.lua | 85 +++++++++++++++++++++++++++++++++++++++++++++ wafconf/args | 22 ++++++++++++ wafconf/cookie | 20 +++++++++++ wafconf/post | 19 ++++++++++ wafconf/url | 6 ++++ wafconf/user-agent | 1 + wafconf/whiteurl | 1 + 10 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 waf_rule_check.lua create mode 100644 wafconf/args create mode 100644 wafconf/cookie create mode 100644 wafconf/post create mode 100644 wafconf/url create mode 100644 wafconf/user-agent create mode 100644 wafconf/whiteurl diff --git a/access_all.lua b/access_all.lua index 9ba17dc..8aa4b90 100644 --- a/access_all.lua +++ b/access_all.lua @@ -1,6 +1,7 @@ ----- access_all by zj ----- local optl = require("optl") local stool = require("stool") +local check = require 'waf_rule_check' local parser = require "resty.bodyparser" local ngx_var = ngx.var local ngx_ctx = ngx.ctx @@ -221,7 +222,18 @@ local function get_post_form(_len) end end ---- SETP 0 +--- STEP -1 +--- 基础攻击检查,基于正则的检查 +if config_is_on("rule_check") then + local block, _type = check.rule_check(next_ctx.base_msg) + if block then + set_count_dict("rule check deny, rule type: ".._type) + next_ctx.waf_log = next_ctx.waf_log or "[rule check] deny, rule type: ".._type + action_deny() + end +end + +--- STEP 0 -- 获取用户真实IP(如有CDN情况下,从header头取) if config_is_on("realIpFrom_Mod") then ip = optl.loc_getRealIp(remoteIp,getDict_Config("realIpFrom_Mod")[host]) diff --git a/conf_json/base.json b/conf_json/base.json index 570edf0..e097573 100644 --- a/conf_json/base.json +++ b/conf_json/base.json @@ -39,6 +39,8 @@ "HPP_state":"on" }, + "rule_check" : "on", + "post_form":10240, "network_Mod" : "on", @@ -55,6 +57,8 @@ "htmlPath" : "/opt/openresty/openstar/index/", + "wafRulePath" : "/opt/openresty/openstar/wafconf/", + "denyMsg" : {"state":"on","msg":"openstar deny","http_code":403}, "log_conf": { diff --git a/init.lua b/init.lua index f7c96c9..47c0eaa 100644 --- a/init.lua +++ b/init.lua @@ -16,6 +16,20 @@ local config_dict = ngx_shared.config_dict local host_dict = ngx_shared.host_dict local ip_dict = ngx_shared.ip_dict +--- 读取 waf rules 文件数据 +function read_rule(rulepath) + local file = io.open(rulepath,"r") + if file==nil then + return + end + local t = {} + for line in file:lines() do + table.insert(t,line) + end + file:close() + return(t) +end + --- 载入config.json全局基础配置 --- 全局函数 @@ -85,6 +99,19 @@ function loadConfig() -- denyMsg list config.denyMsg = stool.loadjson(_basedir.."denyMsg.json") + -- STEP 15 + -- 读取 waf rules 数据 + local waf_rules = {} + local waf_rules_dir = config.base.wafRulePath or "/opt/openresty/openstar/wafconf" + + waf_rules.url_rules = read_rule(waf_rules_dir..'url') + waf_rules.args_rules = read_rule(waf_rules_dir..'args') + waf_rules.uar_rules = read_rule(waf_rules_dir..'user-agent') + waf_rules.cookie_rules = read_rule(waf_rules_dir..'cookie') + waf_rules.post_rules = read_rule(waf_rules_dir..'post') + + config.waf_rules = waf_rules + config_dict:safe_set("config",cjson_safe.encode(config),0) config_dict:safe_set("config_version",0,0) diff --git a/waf_rule_check.lua b/waf_rule_check.lua new file mode 100644 index 0000000..37215c7 --- /dev/null +++ b/waf_rule_check.lua @@ -0,0 +1,85 @@ +--- waf rules check --- +local ngxmatch = ngx.re.match +local optl = require("optl") +local waf_rules = optl.config.waf_rules or {} + +local url_rules = waf_rules.url_rules +local args_rules = waf_rules.args_rules +local uar_rules = waf_rules.uar_rules +local cookie_rules = waf_rules.cookie_rules +local post_rules = waf_rules.post_rules + +local M = {} + +function M.common_check(val, rules) + if val ~= nil then + for _, rule in pairs(rules) do + if rule ~= "" and ngxmatch(val, rule, "isjo") then + return true + end + end + end + return false +end + +function M.check_ua(ua) + return M.common_check(ua, uar_rules) +end + +function M.check_url(request_uri) + return M.common_check(request_uri, url_rules) +end + +function M.check_args(args) + local data = {} + for _, 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 + table.insert(data, t) + else + table.insert(val) + end + end + + for _, rule in pairs(args_rules) do + for _, val in pairs(data) do + if val and type(val) ~= "boolean" and rule ~= nil and ngxmatch(val, rule, "isjo") then + return true + end + end + end + + return false +end + +function M.check_cookie(cookie) + return M.common_check(cookie, cookie_rules) +end + +function M.check_body(body) + return M.common_check(body, post_rules) +end + +function M.rule_check(base_msg) + if M.check_ua(base_msg.useragent) then + return true, "useragent" + elseif M.check_url(base_msg.request_uri) then + return true, "url" + elseif M.check_args(base_msg.args) then + return true, "args" + elseif M.check_cookie(base_msg.cookie) then + return true, "cookie" + elseif M.check_post(base_msg.posts_data) then + return true, "post" + end + + return false, nil +end + +return M \ No newline at end of file diff --git a/wafconf/args b/wafconf/args new file mode 100644 index 0000000..099fb38 --- /dev/null +++ b/wafconf/args @@ -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)\= diff --git a/wafconf/cookie b/wafconf/cookie new file mode 100644 index 0000000..9770d81 --- /dev/null +++ b/wafconf/cookie @@ -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)\[ diff --git a/wafconf/post b/wafconf/post new file mode 100644 index 0000000..d418f96 --- /dev/null +++ b/wafconf/post @@ -0,0 +1,19 @@ +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)\= diff --git a/wafconf/url b/wafconf/url new file mode 100644 index 0000000..934caa3 --- /dev/null +++ b/wafconf/url @@ -0,0 +1,6 @@ +\.(svn|htaccess|bash_history) +\.(bak|inc|old|mdb|sql|backup|java|class)$ +(vhost|bbs|host|wwwroot|www|site|root|hytop|flashfxp).*\.rar +(phpmyadmin|jmx-console|jmxinvokerservlet) +java\.lang +/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\\w+).(php|jsp) diff --git a/wafconf/user-agent b/wafconf/user-agent new file mode 100644 index 0000000..09c73ca --- /dev/null +++ b/wafconf/user-agent @@ -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| SF/) diff --git a/wafconf/whiteurl b/wafconf/whiteurl new file mode 100644 index 0000000..6912a60 --- /dev/null +++ b/wafconf/whiteurl @@ -0,0 +1 @@ +^/123/$