mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-24 22:51:19 +08:00
feat(waf): 优化规则 (#4166)
This commit is contained in:
parent
3b697c7520
commit
77f4f64f0d
25 changed files with 813 additions and 10385 deletions
|
|
@ -2225,6 +2225,20 @@ const message = {
|
||||||
ipEnd: 'End IP',
|
ipEnd: 'End IP',
|
||||||
ipv4: 'IPV4',
|
ipv4: 'IPV4',
|
||||||
ipv6: 'IPV6',
|
ipv6: 'IPV6',
|
||||||
|
urlDefense: 'URL rules',
|
||||||
|
urlHelper: 'Forbidden URL',
|
||||||
|
dirFilter: 'Directory filter',
|
||||||
|
sqlInject: 'SQL injection',
|
||||||
|
xss: 'XSS',
|
||||||
|
phpExec: 'PHP script execution',
|
||||||
|
oneWordTrojan: 'One word Trojan',
|
||||||
|
appFilter: 'Apply dangerous directory filtering',
|
||||||
|
webshell: 'Webshell',
|
||||||
|
args: 'Malicious parameters',
|
||||||
|
protocolFilter: 'Protocol filter',
|
||||||
|
javaFileter: 'Java Dangerous File Filtering',
|
||||||
|
scannerFilter: 'Scanner filter',
|
||||||
|
escapeFilter: 'escape filter',
|
||||||
},
|
},
|
||||||
monitor: {
|
monitor: {
|
||||||
name: 'Website Monitor',
|
name: 'Website Monitor',
|
||||||
|
|
@ -2259,7 +2273,7 @@ const message = {
|
||||||
disableHelper:
|
disableHelper:
|
||||||
'The anti-tampering function of website {0} is about to be disabled. Do you want to continue?',
|
'The anti-tampering function of website {0} is about to be disabled. Do you want to continue?',
|
||||||
},
|
},
|
||||||
setting: {
|
setting: {
|
||||||
setting: 'Interface Settings',
|
setting: 'Interface Settings',
|
||||||
title: 'Panel Description',
|
title: 'Panel Description',
|
||||||
titleHelper:
|
titleHelper:
|
||||||
|
|
|
||||||
|
|
@ -2079,6 +2079,20 @@ const message = {
|
||||||
ipEnd: '結束 IP',
|
ipEnd: '結束 IP',
|
||||||
ipv4: 'IPV4',
|
ipv4: 'IPV4',
|
||||||
ipv6: 'IPV6',
|
ipv6: 'IPV6',
|
||||||
|
urlDefense: 'URL 規則',
|
||||||
|
urlHelper: '禁止存取的 URL',
|
||||||
|
dirFilter: '目錄過濾',
|
||||||
|
sqlInject: 'SQL 注入',
|
||||||
|
xss: 'XSS',
|
||||||
|
phpExec: 'PHP 腳本執行',
|
||||||
|
oneWordTrojan: '一句話木馬',
|
||||||
|
appFilter: '套用危險目錄過濾',
|
||||||
|
webshell: 'Webshell',
|
||||||
|
args: '惡意參數',
|
||||||
|
protocolFilter: '協議過濾',
|
||||||
|
javaFileter: 'Java 危險檔案過濾',
|
||||||
|
scannerFilter: '掃描器過濾',
|
||||||
|
escapeFilter: '轉義過濾',
|
||||||
},
|
},
|
||||||
monitor: {
|
monitor: {
|
||||||
name: '網站監控',
|
name: '網站監控',
|
||||||
|
|
|
||||||
|
|
@ -2056,13 +2056,13 @@ const message = {
|
||||||
sqliHelper: '识别请求中的 SQL 注入并拦截',
|
sqliHelper: '识别请求中的 SQL 注入并拦截',
|
||||||
xssHelper: '识别请求中的 XSS 并拦截',
|
xssHelper: '识别请求中的 XSS 并拦截',
|
||||||
xssDefense: 'XSS 防御',
|
xssDefense: 'XSS 防御',
|
||||||
uaDefense: '恶意 User-Agent 规则',
|
uaDefense: 'User-Agent 规则',
|
||||||
uaHelper: '包含常见的恶意爬虫规则',
|
uaHelper: '包含常见的恶意爬虫规则',
|
||||||
argsDefense: '恶意参数规则',
|
argsDefense: '参数规则',
|
||||||
argsHelper: '禁止请求中携带恶意参数',
|
argsHelper: '禁止请求中携带恶意参数',
|
||||||
cookieDefense: '恶意 Cookie 规则',
|
cookieDefense: 'Cookie 规则',
|
||||||
cookieHelper: '禁止请求中携带恶意 Cookie',
|
cookieHelper: '禁止请求中携带恶意 Cookie',
|
||||||
headerDefense: '恶意 Header 规则',
|
headerDefense: 'Header 规则',
|
||||||
headerHelper: '禁止请求中携带恶意 Header',
|
headerHelper: '禁止请求中携带恶意 Header',
|
||||||
httpRule: 'HTTP 请求方法规则',
|
httpRule: 'HTTP 请求方法规则',
|
||||||
httpHelper: '限制网站的请求方法类型',
|
httpHelper: '限制网站的请求方法类型',
|
||||||
|
|
@ -2079,6 +2079,20 @@ const message = {
|
||||||
ipEnd: '结束 IP',
|
ipEnd: '结束 IP',
|
||||||
ipv4: 'IPV4',
|
ipv4: 'IPV4',
|
||||||
ipv6: 'IPV6',
|
ipv6: 'IPV6',
|
||||||
|
urlDefense: 'URL 规则',
|
||||||
|
urlHelper: '禁止访问的 URL',
|
||||||
|
dirFilter: '目录过滤',
|
||||||
|
sqlInject: 'SQL 注入',
|
||||||
|
xss: 'XSS',
|
||||||
|
phpExec: 'PHP 脚本执行',
|
||||||
|
oneWordTrojan: '一句话木马',
|
||||||
|
appFilter: '应用危险目录过滤',
|
||||||
|
webshell: 'Webshell',
|
||||||
|
args: '恶意参数',
|
||||||
|
protocolFilter: '协议过滤',
|
||||||
|
javaFileter: 'Java 危险文件过滤',
|
||||||
|
scannerFilter: '扫描器过滤',
|
||||||
|
escapeFilter: '转义过滤',
|
||||||
},
|
},
|
||||||
monitor: {
|
monitor: {
|
||||||
name: '网站监控',
|
name: '网站监控',
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
"action": "deny"
|
"action": "deny"
|
||||||
},
|
},
|
||||||
"notFoundCount": {
|
"notFoundCount": {
|
||||||
"state": "on",
|
"state": "off",
|
||||||
"type": "notFoundCount",
|
"type": "notFoundCount",
|
||||||
"threshold": 10,
|
"threshold": 10,
|
||||||
"duration": 60,
|
"duration": 60,
|
||||||
|
|
@ -85,18 +85,18 @@
|
||||||
"action": "deny"
|
"action": "deny"
|
||||||
},
|
},
|
||||||
"cc": {
|
"cc": {
|
||||||
"state": "on",
|
"state": "off",
|
||||||
"type": "cc",
|
"type": "cc",
|
||||||
"rule": "cc",
|
"rule": "cc",
|
||||||
"tokenTimeOut": 1800,
|
"tokenTimeOut": 1800,
|
||||||
"threshold": 100,
|
"threshold": 120,
|
||||||
"duration": 60,
|
"duration": 60,
|
||||||
"action": "deny",
|
"action": "deny",
|
||||||
"ipBlock": "on",
|
"ipBlock": "on",
|
||||||
"ipBlockTime": 600
|
"ipBlockTime": 600
|
||||||
},
|
},
|
||||||
"ccurl": {
|
"ccurl": {
|
||||||
"state": "on",
|
"state": "off",
|
||||||
"type": "urlcc",
|
"type": "urlcc",
|
||||||
"rule": "urlcc",
|
"rule": "urlcc",
|
||||||
"action": "deny",
|
"action": "deny",
|
||||||
|
|
@ -104,7 +104,7 @@
|
||||||
"ipBlockTime": 600
|
"ipBlockTime": 600
|
||||||
},
|
},
|
||||||
"attackCount": {
|
"attackCount": {
|
||||||
"state": "on",
|
"state": "off",
|
||||||
"type": "attackCount",
|
"type": "attackCount",
|
||||||
"threshold": 20,
|
"threshold": 20,
|
||||||
"duration": 60,
|
"duration": 60,
|
||||||
|
|
@ -143,6 +143,12 @@
|
||||||
"code": 403,
|
"code": 403,
|
||||||
"action": "deny"
|
"action": "deny"
|
||||||
},
|
},
|
||||||
|
"defaultUrlBlack": {
|
||||||
|
"type": "defaultUrlBlack",
|
||||||
|
"state": "on",
|
||||||
|
"code": 403,
|
||||||
|
"action": "deny"
|
||||||
|
},
|
||||||
"args": {
|
"args": {
|
||||||
"type": "args",
|
"type": "args",
|
||||||
"state": "on",
|
"state": "on",
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ local function init_global_config()
|
||||||
rules.args = read_rule(global_rule_dir, "args")
|
rules.args = read_rule(global_rule_dir, "args")
|
||||||
rules.cookie = read_rule(global_rule_dir, "cookie")
|
rules.cookie = read_rule(global_rule_dir, "cookie")
|
||||||
rules.defaultUaBlack = read_rule(global_rule_dir, "defaultUaBlack")
|
rules.defaultUaBlack = read_rule(global_rule_dir, "defaultUaBlack")
|
||||||
|
rules.defaultUrlBlack = read_rule(global_rule_dir, "defaultUrlBlack")
|
||||||
rules.header = read_rule(global_rule_dir, "header")
|
rules.header = read_rule(global_rule_dir, "header")
|
||||||
|
|
||||||
config.global_rules = rules
|
config.global_rules = rules
|
||||||
|
|
@ -101,6 +102,7 @@ local function init_global_config()
|
||||||
_M.waf_dir = waf_dir
|
_M.waf_dir = waf_dir
|
||||||
_M.waf_db_dir = waf_dir .. "db/"
|
_M.waf_db_dir = waf_dir .. "db/"
|
||||||
_M.waf_db_path = _M.waf_db_dir .. "1pwaf.db"
|
_M.waf_db_path = _M.waf_db_dir .. "1pwaf.db"
|
||||||
|
_M.waf_log_db_path = _M.waf_db_dir .. "req_log.db"
|
||||||
_M.config_dir = config_dir
|
_M.config_dir = config_dir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ local function check_table(table_name,wafdb)
|
||||||
return rows > 0
|
return rows > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function _M.init()
|
local function init_db_config(db_path)
|
||||||
local ok, sqlite3 = pcall(function()
|
local ok, sqlite3 = pcall(function()
|
||||||
return require "lsqlite3"
|
return require "lsqlite3"
|
||||||
end)
|
end)
|
||||||
|
|
@ -36,8 +36,7 @@ function _M.init()
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local wafdb
|
local wafdb
|
||||||
init_dir(config.waf_db_dir)
|
wafdb = sqlite3.open(db_path)
|
||||||
wafdb = sqlite3.open(config.waf_db_path)
|
|
||||||
if wafdb == nil then
|
if wafdb == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
@ -45,50 +44,17 @@ function _M.init()
|
||||||
wafdb:exec([[PRAGMA synchronous = 0]])
|
wafdb:exec([[PRAGMA synchronous = 0]])
|
||||||
wafdb:exec([[PRAGMA page_size = 8192]])
|
wafdb:exec([[PRAGMA page_size = 8192]])
|
||||||
wafdb:exec([[PRAGMA journal_size_limit = 2147483648]])
|
wafdb:exec([[PRAGMA journal_size_limit = 2147483648]])
|
||||||
|
return wafdb
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.init()
|
||||||
|
init_dir(config.waf_db_dir)
|
||||||
|
local wafdb = init_db_config(config.waf_db_path)
|
||||||
|
if not wafdb then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local status = {}
|
local status = {}
|
||||||
if not check_table("attack_log",wafdb) then
|
|
||||||
status = wafdb:exec([[
|
|
||||||
CREATE TABLE req_logs (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
ip TEXT,
|
|
||||||
ip_iso TEXT,
|
|
||||||
ip_country_zh TEXT,
|
|
||||||
ip_country_en TEXT,
|
|
||||||
ip_province_zh TEXT,
|
|
||||||
ip_province_en TEXT,
|
|
||||||
ip_longitude TEXT,
|
|
||||||
ip_latitude TEXT,
|
|
||||||
time INTEGER,
|
|
||||||
localtime TEXT,
|
|
||||||
server_name TEXT,
|
|
||||||
website_key TEXT,
|
|
||||||
host TEXT,
|
|
||||||
method TEXT,
|
|
||||||
uri TEXT,
|
|
||||||
user_agent TEXT,
|
|
||||||
rule_type TEXT,
|
|
||||||
match_rule TEXT,
|
|
||||||
match_value TEXT,
|
|
||||||
nginx_log TEXT,
|
|
||||||
blocking_time INTEGER,
|
|
||||||
action TEXT,
|
|
||||||
is_block INTEGER,
|
|
||||||
is_attack INTEGER
|
|
||||||
)]])
|
|
||||||
end
|
|
||||||
|
|
||||||
if not check_table("block_ip",wafdb) then
|
|
||||||
status = wafdb:exec([[
|
|
||||||
CREATE TABLE block_ip (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
ip TEXT,
|
|
||||||
is_block INTEGER,
|
|
||||||
attack_log_id INTEGER
|
|
||||||
)]])
|
|
||||||
|
|
||||||
ngx.log(ngx.ERR, "init block_ip status"..status)
|
|
||||||
end
|
|
||||||
|
|
||||||
if not check_table("waf_stat",wafdb) then
|
if not check_table("waf_stat",wafdb) then
|
||||||
status = wafdb:exec([[
|
status = wafdb:exec([[
|
||||||
CREATE TABLE waf_stat (
|
CREATE TABLE waf_stat (
|
||||||
|
|
@ -102,6 +68,51 @@ function _M.init()
|
||||||
)]])
|
)]])
|
||||||
ngx.log(ngx.ERR, "init waf_stat status"..status)
|
ngx.log(ngx.ERR, "init waf_stat status"..status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local logdb = init_db_config(config.waf_log_db_path)
|
||||||
|
if not check_table("req_logs",logdb) then
|
||||||
|
status = logdb:exec([[
|
||||||
|
CREATE TABLE req_logs (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
ip TEXT,
|
||||||
|
ip_iso TEXT,
|
||||||
|
ip_country_zh TEXT,
|
||||||
|
ip_country_en TEXT,
|
||||||
|
ip_province_zh TEXT,
|
||||||
|
ip_province_en TEXT,
|
||||||
|
ip_longitude TEXT,
|
||||||
|
ip_latitude TEXT,
|
||||||
|
localtime DATETIME,
|
||||||
|
server_name TEXT,
|
||||||
|
website_key TEXT,
|
||||||
|
host TEXT,
|
||||||
|
method TEXT,
|
||||||
|
uri TEXT,
|
||||||
|
user_agent TEXT,
|
||||||
|
exec_rule TEXT,
|
||||||
|
rule_type TEXT,
|
||||||
|
match_rule TEXT,
|
||||||
|
match_value TEXT,
|
||||||
|
nginx_log TEXT,
|
||||||
|
blocking_time INTEGER,
|
||||||
|
action TEXT,
|
||||||
|
is_block INTEGER,
|
||||||
|
is_attack INTEGER
|
||||||
|
)]])
|
||||||
|
end
|
||||||
|
|
||||||
|
if not check_table("block_ips",logdb) then
|
||||||
|
status = logdb:exec([[
|
||||||
|
CREATE TABLE block_ips (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
ip TEXT,
|
||||||
|
is_block INTEGER,
|
||||||
|
blocking_time INTEGER,
|
||||||
|
req_log_id TEXT,
|
||||||
|
create_date DATETIME
|
||||||
|
)]])
|
||||||
|
ngx.log(ngx.ERR, "init block_ip status"..status)
|
||||||
|
end
|
||||||
|
|
||||||
ngx.log(ngx.ERR, "init db success")
|
ngx.log(ngx.ERR, "init db success")
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
local db = require "db"
|
local db = require "db"
|
||||||
local config = require "config"
|
local config = require "config"
|
||||||
local geoip = require "geoip"
|
|
||||||
|
|
||||||
config.load_config_file()
|
config.load_config_file()
|
||||||
db.init()
|
db.init()
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,10 @@ end
|
||||||
|
|
||||||
function _M.block_ip(ip, rule)
|
function _M.block_ip(ip, rule)
|
||||||
local ok, err = nil, nil
|
local ok, err = nil, nil
|
||||||
local msg = "拉黑IP : " .. ip .. "国家 " .. ngx.ctx.geoip.country["zh"]
|
local msg = "拉黑IP : " .. ip .. "国家 " .. ngx.ctx.ip_location.country["zh"]
|
||||||
if rule then
|
if rule then
|
||||||
msg = msg .. " 规则 " .. rule.type
|
msg = msg .. " 规则 " .. rule.type
|
||||||
end
|
end
|
||||||
|
|
||||||
ngx.log(ngx.ERR, msg)
|
ngx.log(ngx.ERR, msg)
|
||||||
|
|
||||||
if config.redis_on then
|
if config.redis_on then
|
||||||
|
|
@ -56,7 +55,7 @@ function _M.block_ip(ip, rule)
|
||||||
if exists == 0 then
|
if exists == 0 then
|
||||||
ok, err = red:set(key, 1)
|
ok, err = red:set(key, 1)
|
||||||
if ok then
|
if ok then
|
||||||
ngx.ctx.ipBlocked = true
|
ngx.ctx.ip_blocked = true
|
||||||
else
|
else
|
||||||
ngx.log(ngx.ERR, "failed to set redis key " .. key, err)
|
ngx.log(ngx.ERR, "failed to set redis key " .. key, err)
|
||||||
end
|
end
|
||||||
|
|
@ -76,14 +75,14 @@ function _M.block_ip(ip, rule)
|
||||||
if not exists then
|
if not exists then
|
||||||
ok, err = wafBlackIp:set(ip, 1, rule.ipBlockTime)
|
ok, err = wafBlackIp:set(ip, 1, rule.ipBlockTime)
|
||||||
if ok then
|
if ok then
|
||||||
ngx.ctx.ipBlocked = true
|
ngx.ctx.ip_blocked = true
|
||||||
else
|
else
|
||||||
ngx.log(ngx.ERR, "failed to set key " .. ip, err)
|
ngx.log(ngx.ERR, "failed to set key " .. ip, err)
|
||||||
end
|
end
|
||||||
elseif rule.ipBlockTime > 0 then
|
elseif rule.ipBlockTime > 0 then
|
||||||
ok, err = wafBlackIp:expire(ip, rule.ipBlockTime)
|
ok, err = wafBlackIp:expire(ip, rule.ipBlockTime)
|
||||||
if ok then
|
if ok then
|
||||||
ngx.ctx.ipBlocked = true
|
ngx.ctx.ip_blocked = true
|
||||||
else
|
else
|
||||||
ngx.log(ngx.ERR, "failed to expire key " .. ip, err)
|
ngx.log(ngx.ERR, "failed to expire key " .. ip, err)
|
||||||
end
|
end
|
||||||
|
|
@ -128,15 +127,10 @@ end
|
||||||
|
|
||||||
function _M.exec_action(rule_config, match_rule, data)
|
function _M.exec_action(rule_config, match_rule, data)
|
||||||
local action = rule_config.action
|
local action = rule_config.action
|
||||||
|
|
||||||
if match_rule then
|
if match_rule then
|
||||||
rule_config.rule = match_rule.rule
|
rule_config.match_rule = match_rule
|
||||||
else
|
|
||||||
rule_config.rule = "默认"
|
|
||||||
end
|
end
|
||||||
|
ngx.ctx.exec_rule = rule_config
|
||||||
ngx.ctx.rule_table = rule_config
|
|
||||||
ngx.ctx.action = action
|
|
||||||
ngx.ctx.hitData = data
|
ngx.ctx.hitData = data
|
||||||
ngx.ctx.is_attack = true
|
ngx.ctx.is_attack = true
|
||||||
|
|
||||||
|
|
@ -144,13 +138,12 @@ function _M.exec_action(rule_config, match_rule, data)
|
||||||
_M.block_ip(ngx.ctx.ip, rule_config)
|
_M.block_ip(ngx.ctx.ip, rule_config)
|
||||||
end
|
end
|
||||||
|
|
||||||
if rule_config.type == nil then
|
|
||||||
rule_config.type = "默认"
|
|
||||||
end
|
|
||||||
|
|
||||||
attack_count(rule_config.type)
|
attack_count(rule_config.type)
|
||||||
|
|
||||||
local msg = "访问 IP " .. ngx.ctx.ip .. " 访问 URL" .. ngx.var.uri .. " 触发动作 " .. action .. " User-Agent " .. ngx.ctx.ua .. " 规则类型 " .. rule_config.type .. " 规则 " .. rule_config.rule
|
local msg = "访问 IP " .. ngx.ctx.ip .. " 访问 URL" .. ngx.var.uri .. " 触发动作 " .. action .. " 规则类型 " .. rule_config.type
|
||||||
|
if match_rule then
|
||||||
|
msg = msg .. " 触发规则 " .. match_rule.type
|
||||||
|
end
|
||||||
|
|
||||||
ngx.log(ngx.ERR, msg)
|
ngx.log(ngx.ERR, msg)
|
||||||
if action == "allow" then
|
if action == "allow" then
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ local ck = require "resty.cookie"
|
||||||
local geo = require "geoip"
|
local geo = require "geoip"
|
||||||
local libinjection = require "resty.libinjection"
|
local libinjection = require "resty.libinjection"
|
||||||
local config = require "config"
|
local config = require "config"
|
||||||
local cjson = require "cjson"
|
|
||||||
local utils = require "utils"
|
local utils = require "utils"
|
||||||
|
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
|
|
@ -14,12 +13,13 @@ local ipairs = ipairs
|
||||||
local tostring = tostring
|
local tostring = tostring
|
||||||
local type = type
|
local type = type
|
||||||
local next = next
|
local next = next
|
||||||
local tonumber = tonumber
|
|
||||||
local concat_table = table.concat
|
local concat_table = table.concat
|
||||||
local ngx_re_find = ngx.re.find
|
local ngx_re_find = ngx.re.find
|
||||||
local decode = cjson.decode
|
|
||||||
local ngx_re_gmatch = ngx.re.gmatch
|
local ngx_re_gmatch = ngx.re.gmatch
|
||||||
local ngx_re_match = ngx.re.match
|
local ngx_re_match = ngx.re.match
|
||||||
|
local ipv4_to_int = utils.ipv4_to_int
|
||||||
|
local is_ip_in_array = utils.is_ip_in_array
|
||||||
|
local is_ipv6 = utils.is_ipv6
|
||||||
|
|
||||||
local exec_action = action.exec_action
|
local exec_action = action.exec_action
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ local function match_ip(ip_rule, ip, ipn)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local ip_rule_type = ip_rule.type
|
local ip_rule_type = ip_rule.type
|
||||||
if utils.is_ipv6(ip) and ip_rule_type == "ipv6" then
|
if is_ipv6(ip) and ip_rule_type == "ipv6" then
|
||||||
if ip == ip_rule.ipv6 then
|
if ip == ip_rule.ipv6 then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
@ -105,12 +105,13 @@ local function match_ip(ip_rule, ip, ipn)
|
||||||
end
|
end
|
||||||
|
|
||||||
if ip_rule.type == "ipv4" then
|
if ip_rule.type == "ipv4" then
|
||||||
if ipn == tonumber(ip_rule.ipv4) then
|
if ipn == ipv4_to_int(ip_rule.ipv4) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
elseif ip_rule.type == "ipArr" then
|
elseif ip_rule.type == "ipArr" then
|
||||||
local ipArr = ip_rule.ipArr
|
local ip_start_n = ipv4_to_int(ip_rule.ipStart)
|
||||||
if utils.is_ip_in_array(ipn, ipArr.start, ipArr["end"]) then
|
local ip_end_n = ipv4_to_int(ip_rule.ipEnd)
|
||||||
|
if is_ip_in_array(ipn, ip_start_n, ip_end_n) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
elseif ip_rule.type == "ipGroup" then
|
elseif ip_rule.type == "ipGroup" then
|
||||||
|
|
@ -120,34 +121,50 @@ local function match_ip(ip_rule, ip, ipn)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local function xss_and_sql_check(body)
|
local function get_boundary()
|
||||||
if body then
|
local header = utils.get_headers()["content-type"]
|
||||||
if is_global_state_on("xss") or is_global_state_on("sql") then
|
if not header then
|
||||||
for k, v in pairs(body) do
|
return nil
|
||||||
if type(v) == 'string' then
|
|
||||||
if is_site_state_on("xss") then
|
|
||||||
local is_xss, fingerprint = libinjection.xss(tostring(v))
|
|
||||||
local xss_config = get_site_config("xss")
|
|
||||||
if is_xss then
|
|
||||||
exec_action(xss_config, { rule = tostring(k) .. '=' .. tostring(v) })
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if is_site_state_on("sql") then
|
|
||||||
local is_sqli, fingerprint = libinjection.sqli(tostring(v))
|
|
||||||
local sql_config = get_site_config("sql")
|
|
||||||
if is_sqli then
|
|
||||||
exec_action(sql_config, { rule = tostring(k) .. '=' .. tostring(v) })
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if type(header) == "table" then
|
||||||
|
header = header[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
local m = ngx_re_match(header, ";%s*boundary=\"([^\"]+)\"")
|
||||||
|
if m then
|
||||||
|
return m
|
||||||
|
end
|
||||||
|
|
||||||
|
return ngx_re_match(header, ";%s*boundary=([^\",;]+)")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function xss_and_sql_check(kv)
|
||||||
|
if type(kv) ~= 'string' then
|
||||||
|
return
|
||||||
|
|
||||||
|
end
|
||||||
|
if is_site_state_on("xss") then
|
||||||
|
local is_xss, fingerprint = libinjection.xss(tostring(kv))
|
||||||
|
local xss_config = get_site_config("xss")
|
||||||
|
if is_xss then
|
||||||
|
exec_action(xss_config, { rule = kv })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if is_site_state_on("sql") then
|
||||||
|
local is_sqli, fingerprint = libinjection.sqli(tostring(kv))
|
||||||
|
local sql_config = get_site_config("sql")
|
||||||
|
if is_sqli then
|
||||||
|
exec_action(sql_config, { rule = kv })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_request_body()
|
local function get_request_body()
|
||||||
ngx.req.read_body()
|
ngx.req.read_body()
|
||||||
local body_data = ngx.req.get_body_data()
|
local body_data = ngx.req.get_body_data()
|
||||||
|
|
@ -182,9 +199,9 @@ end
|
||||||
|
|
||||||
function _M.allow_location_check()
|
function _M.allow_location_check()
|
||||||
if is_state_on("geoRestrict") then
|
if is_state_on("geoRestrict") then
|
||||||
local geo_ip = ngx.ctx.geoip
|
local ip_location = ngx.ctx.ip_location
|
||||||
if geo_ip and geo_ip.iso and geo_ip.iso ~= "" then
|
if ip_location and ip_location.iso and ip_location.iso ~= "" then
|
||||||
local iso = geo_ip.iso
|
local iso = ip_location.iso
|
||||||
local geo_config = get_site_config("geoRestrict")
|
local geo_config = get_site_config("geoRestrict")
|
||||||
local exist = false
|
local exist = false
|
||||||
for _, rule in ipairs(geo_config.rules) do
|
for _, rule in ipairs(geo_config.rules) do
|
||||||
|
|
@ -233,7 +250,7 @@ function _M.black_ip()
|
||||||
if ip == "unknown" then
|
if ip == "unknown" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local exists = nil
|
local exists = false
|
||||||
|
|
||||||
if config.is_redis_on() then
|
if config.is_redis_on() then
|
||||||
exists = redis_util.get("black_ip:" .. ip)
|
exists = redis_util.get("black_ip:" .. ip)
|
||||||
|
|
@ -241,14 +258,12 @@ function _M.black_ip()
|
||||||
exists = ngx.shared.waf_black_ip:get(ip)
|
exists = ngx.shared.waf_black_ip:get(ip)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not exists then
|
local ip_black_list = get_global_rules("ipBlack")
|
||||||
local ip_black_list = get_global_rules("ipBlack")
|
local ipn = ipv4_to_int(ip)
|
||||||
local ipn = utils.ipv4_to_int(ip)
|
for _, ip_rule in pairs(ip_black_list) do
|
||||||
for _, ip_rule in pairs(ip_black_list) do
|
if match_ip(ip_rule, ip, ipn) then
|
||||||
if match_ip(ip_rule, ip, ipn) then
|
exists = true
|
||||||
exists = true
|
break
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -424,6 +439,20 @@ function _M.black_url()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function _M.default_url_black()
|
||||||
|
if is_state_on("defaultUrlBlack") then
|
||||||
|
local url = ngx.var.uri
|
||||||
|
if url == nil or url == "" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local m, mr = match_rule(get_global_rules('defaultUrlBlack'), url)
|
||||||
|
if m then
|
||||||
|
exec_action(get_global_config('defaultUrlBlack'), mr)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function _M.args_check()
|
function _M.args_check()
|
||||||
if is_state_on("args") then
|
if is_state_on("args") then
|
||||||
local args = ngx.req.get_uri_args()
|
local args = ngx.req.get_uri_args()
|
||||||
|
|
@ -436,13 +465,14 @@ function _M.args_check()
|
||||||
end
|
end
|
||||||
if val_arr and type(val_arr) ~= "boolean" and val_arr ~= "" then
|
if val_arr and type(val_arr) ~= "boolean" and val_arr ~= "" then
|
||||||
local m, mr = match_rule(args_list, utils.unescape_uri(val_arr))
|
local m, mr = match_rule(args_list, utils.unescape_uri(val_arr))
|
||||||
|
ngx.log(ngx.ERR, "args_check: ", m, " ", mr.rule, " ", val_arr)
|
||||||
if m then
|
if m then
|
||||||
exec_action(get_global_config("args"), mr)
|
exec_action(get_global_config("args"), mr)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
xss_and_sql_check(val_arr)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
xss_and_sql_check(args)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -453,8 +483,7 @@ function _M.cookie_check()
|
||||||
local cookieList = get_site_rule('cookie')
|
local cookieList = get_site_rule('cookie')
|
||||||
local m, mr = match_rule(cookieList, cookie)
|
local m, mr = match_rule(cookieList, cookie)
|
||||||
if m then
|
if m then
|
||||||
local rule_config = get_global_config('cookie')
|
exec_action(get_global_config('cookie'), mr)
|
||||||
exec_action(rule_config, mr)
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -500,15 +529,10 @@ function _M.post_check()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if ngx_re_find(content_type, '^application/json', "ijo") then
|
local boundary = get_boundary()
|
||||||
local data = get_request_body()
|
|
||||||
if data then
|
|
||||||
xss_and_sql_check(decode(data))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_site_state_on('fileExtCheck') and ngx_re_find(content_type, [[multipart]], 'ijo') then
|
if boundary and is_site_state_on('fileExtCheck') then
|
||||||
if not ngx_re_match(content_type, '^multipart/form-data; boundary=') then
|
if not ngx_re_match(content_type, '^multipart/form-data; boundary=') or not ngx_re_find(content_type, [[multipart]], 'ijo')then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local boundary_value = ngx_re_match(content_type, '^multipart/form-data; boundary=(.+)')
|
local boundary_value = ngx_re_match(content_type, '^multipart/form-data; boundary=(.+)')
|
||||||
|
|
@ -541,6 +565,27 @@ function _M.post_check()
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
ngx.req.read_body()
|
||||||
|
local body_obj = ngx.req.get_post_args()
|
||||||
|
if not body_obj then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for key, val in pairs(body_obj) do
|
||||||
|
if is_global_state_on("xss") or is_global_state_on("sql") then
|
||||||
|
xss_and_sql_check(key)
|
||||||
|
xss_and_sql_check(val)
|
||||||
|
end
|
||||||
|
if is_state_on("args") then
|
||||||
|
local post_rules = get_global_rules("args")
|
||||||
|
local m, mr = match_rule(post_rules, val)
|
||||||
|
if m then
|
||||||
|
exec_action(get_global_config("args"), mr)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ local ipairs = ipairs
|
||||||
local type = type
|
local type = type
|
||||||
local find_str = string.find
|
local find_str = string.find
|
||||||
local gmatch_str = string.gmatch
|
local gmatch_str = string.gmatch
|
||||||
|
local pcall = pcall
|
||||||
local cjson = require "cjson"
|
local cjson = require "cjson"
|
||||||
|
|
||||||
local _M = {}
|
local _M = {}
|
||||||
|
|
@ -116,15 +117,13 @@ function _M.get_real_ip()
|
||||||
return "unknown"
|
return "unknown"
|
||||||
end
|
end
|
||||||
|
|
||||||
function _M.get_geo_ip(ip)
|
function _M.get_ip_location(ip)
|
||||||
if _M.is_intranet_address(ip) then
|
if _M.is_intranet_address(ip) then
|
||||||
return {
|
return {
|
||||||
country = { ["zh"] = "内网", ["en"] = "intranet" },
|
country = { ["zh"] = "内网", ["en"] = "Intranet" },
|
||||||
province = { ["zh"] = "内网", ["en"] = "intranet" },
|
|
||||||
city = { ["zh"] = "内网", ["en"] = "intranet" },
|
|
||||||
longitude = 0,
|
longitude = 0,
|
||||||
latitude = 0,
|
latitude = 0,
|
||||||
iso = "local"
|
iso = "Local"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
geoip.init()
|
geoip.init()
|
||||||
|
|
|
||||||
|
|
@ -7,103 +7,111 @@ local uuid = require"resty.uuid"
|
||||||
local upper_str = string.upper
|
local upper_str = string.upper
|
||||||
local tonumber = tonumber
|
local tonumber = tonumber
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
|
local type = type
|
||||||
|
local concat_table = table.concat
|
||||||
|
|
||||||
local function write_req_log(wafdb,attack)
|
local function write_req_log(attack)
|
||||||
local rule_table = nil
|
local wafdb = utils.get_wafdb(config.waf_log_db_path)
|
||||||
local action = ""
|
if not wafdb then
|
||||||
local rule = nil
|
ngx.log(ngx.ERR, "get log db failed")
|
||||||
local rule_type = ""
|
return
|
||||||
local is_attack = 0
|
|
||||||
local is_block = 0
|
|
||||||
local blocking_time = 0
|
|
||||||
|
|
||||||
if attack then
|
|
||||||
rule_table = ngx.ctx.rule_table
|
|
||||||
action = ngx.ctx.action
|
|
||||||
rule = rule_table.rule
|
|
||||||
rule_type = rule_table.type
|
|
||||||
is_attack = 1
|
|
||||||
if not rule_type then
|
|
||||||
rule_type = "default"
|
|
||||||
end
|
|
||||||
if ngx.ctx.ipBlocked then
|
|
||||||
is_block = 1
|
|
||||||
blocking_time = tonumber(rule_table.ipBlockTime)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local real_ip = ngx.ctx.ip
|
local real_ip = ngx.ctx.ip
|
||||||
local geoip = ngx.ctx.geoip
|
local ip_location = ngx.ctx.ip_location
|
||||||
local country
|
local country
|
||||||
local province
|
local province
|
||||||
local longitude = 0.0
|
local longitude = 0.0
|
||||||
local latitude = 0.0
|
local latitude = 0.0
|
||||||
local iso = "CN"
|
local iso = "CN"
|
||||||
if geoip then
|
if ip_location then
|
||||||
country = geoip.country
|
country = ip_location.country or {
|
||||||
province = geoip.province
|
|
||||||
longitude = geoip.longitude
|
|
||||||
latitude = geoip.latitude
|
|
||||||
iso = geoip.iso
|
|
||||||
else
|
|
||||||
ngx.log(ngx.ERR, real_ip .. " 无法获取地址")
|
|
||||||
end
|
|
||||||
if not country then
|
|
||||||
country = {
|
|
||||||
["zh"] = "unknown",
|
["zh"] = "unknown",
|
||||||
["en"] = "unknown"
|
["en"] = "unknown"
|
||||||
}
|
}
|
||||||
end
|
province = ip_location.province or {
|
||||||
if not province then
|
["zh"] = "",
|
||||||
province = {
|
["en"] = ""
|
||||||
["zh"] = "unknown",
|
|
||||||
["en"] = "unknown"
|
|
||||||
}
|
}
|
||||||
|
longitude = ip_location.longitude
|
||||||
|
latitude = ip_location.latitude
|
||||||
|
iso = ip_location.iso
|
||||||
end
|
end
|
||||||
|
|
||||||
local method = ngx.req.get_method()
|
local exec_rule = {}
|
||||||
local uri = ngx.var.request_uri
|
local rule_action = ""
|
||||||
local ua = ngx.ctx.ua
|
local exec_rule_type = ""
|
||||||
local host = ngx.var.server_name
|
local match_rule_detail = ""
|
||||||
local protocol = ngx.var.server_protocol
|
local match_rule_type = ""
|
||||||
local website_key = ngx.ctx.website_key
|
local is_attack = 0
|
||||||
|
local is_block = 0
|
||||||
local logs_str = method .. " " .. uri .. " "..protocol.."\n"
|
local blocking_time = 0
|
||||||
local headers = ngx.req.get_headers(20000)
|
|
||||||
for k, v in pairs(headers) do
|
local method = ""
|
||||||
local value = ""
|
local uri = ""
|
||||||
if v then
|
local ua = ""
|
||||||
if type(v) == "table" then
|
local host = ""
|
||||||
value = table.concat(v, ",")
|
local protocol = ""
|
||||||
else
|
local website_key = ""
|
||||||
value = v
|
local logs_str = ""
|
||||||
end
|
|
||||||
|
if attack then
|
||||||
|
exec_rule = ngx.ctx.exec_rule
|
||||||
|
rule_action = exec_rule.action
|
||||||
|
exec_rule_type = exec_rule.type
|
||||||
|
is_attack = 1
|
||||||
|
method = ngx.req.get_method()
|
||||||
|
uri = ngx.var.request_uri
|
||||||
|
ua = ngx.ctx.ua
|
||||||
|
host = ngx.var.server_name
|
||||||
|
protocol = ngx.var.server_protocol or ""
|
||||||
|
website_key = ngx.ctx.website_key
|
||||||
|
|
||||||
|
if exec_rule.match_rule then
|
||||||
|
match_rule_detail = exec_rule.match_rule.rule
|
||||||
|
match_rule_type = exec_rule.match_rule.type
|
||||||
|
end
|
||||||
|
|
||||||
|
if ngx.ctx.ip_blocked then
|
||||||
|
is_block = 1
|
||||||
|
blocking_time = tonumber(exec_rule.ipBlockTime)
|
||||||
|
end
|
||||||
|
|
||||||
|
logs_str = method .. " " .. uri .. " "..protocol.."\n"
|
||||||
|
local headers = ngx.req.get_headers(20000)
|
||||||
|
for k, v in pairs(headers) do
|
||||||
|
local value = ""
|
||||||
|
if v then
|
||||||
|
if type(v) == "table" then
|
||||||
|
value = concat_table(v, ",")
|
||||||
|
else
|
||||||
|
value = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
logs_str = logs_str .. upper_str(k) .. ": " .. value .. "\n"
|
||||||
end
|
end
|
||||||
logs_str = logs_str .. upper_str(k) .. ": " .. value .. "\n"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local log_id = uuid()
|
local log_id = uuid()
|
||||||
local time = os.time()
|
|
||||||
local localtime = os.date("%Y-%m-%d %H:%M:%S", time)
|
|
||||||
|
|
||||||
local insertQuery = [[
|
local insertQuery = [[
|
||||||
INSERT INTO req_logs (
|
INSERT INTO req_logs (
|
||||||
id, ip, ip_iso, ip_country_zh, ip_country_en,
|
id, ip, ip_iso, ip_country_zh, ip_country_en,
|
||||||
ip_province_zh, ip_province_en, ip_longitude, ip_latitude,
|
ip_province_zh, ip_province_en, ip_longitude, ip_latitude,
|
||||||
time, localtime, server_name, website_key, host, method,
|
localtime, server_name, website_key, host, method,
|
||||||
uri, user_agent, rule_type,match_rule, match_value,
|
uri, user_agent, exec_rule, rule_type, match_rule, match_value,
|
||||||
nginx_log, blocking_time, action, is_block,is_attack
|
nginx_log, blocking_time, action, is_block,is_attack
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:id, :real_ip, :iso, :country_zh, :country_en,
|
:id, :real_ip, :iso, :country_zh, :country_en,
|
||||||
:province_zh, :province_en,:longitude, :latitude,
|
:province_zh, :province_en,:longitude, :latitude,
|
||||||
:time, :localtime, :server_name,:host, :website_key, :method,
|
DATETIME('now'), :server_name,:host, :website_key, :method,
|
||||||
:uri, :ua, :rule_type, :match_rule, :match_value,
|
:uri, :ua, :exec_rule, :rule_type, :match_rule, :match_value,
|
||||||
:logs_str, :blocking_time, :action, :is_block, :is_attack
|
:logs_str, :blocking_time, :action, :is_block, :is_attack
|
||||||
)
|
)
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
wafdb:execute([[BEGIN TRANSACTION]])
|
||||||
|
|
||||||
local stmt = wafdb:prepare(insertQuery)
|
local stmt = wafdb:prepare(insertQuery)
|
||||||
|
|
||||||
stmt:bind_names {
|
stmt:bind_names {
|
||||||
id = log_id,
|
id = log_id,
|
||||||
iso = iso,
|
iso = iso,
|
||||||
|
|
@ -114,31 +122,48 @@ local function write_req_log(wafdb,attack)
|
||||||
province_en = province["en"],
|
province_en = province["en"],
|
||||||
longitude = longitude,
|
longitude = longitude,
|
||||||
latitude = latitude,
|
latitude = latitude,
|
||||||
time = time,
|
|
||||||
localtime = localtime,
|
|
||||||
host = host,
|
host = host,
|
||||||
server_name = host,
|
server_name = host,
|
||||||
website_key = website_key,
|
website_key = website_key,
|
||||||
method = method,
|
method = method,
|
||||||
uri = uri,
|
uri = uri,
|
||||||
ua = ua,
|
ua = ua,
|
||||||
rule_type = rule_type,
|
exec_rule = exec_rule_type,
|
||||||
match_rule = rule,
|
rule_type = match_rule_type,
|
||||||
|
match_rule = match_rule_detail,
|
||||||
match_value = "",
|
match_value = "",
|
||||||
logs_str = logs_str,
|
logs_str = logs_str,
|
||||||
blocking_time = blocking_time or 0,
|
blocking_time = blocking_time or 0,
|
||||||
action = action,
|
action = rule_action,
|
||||||
is_block = is_block,
|
is_block = is_block,
|
||||||
is_attack = is_attack
|
is_attack = is_attack
|
||||||
}
|
}
|
||||||
|
|
||||||
local code = stmt:step()
|
local code = stmt:step()
|
||||||
stmt:finalize()
|
stmt:finalize()
|
||||||
|
|
||||||
if code ~= 101 then
|
local code2 = 101
|
||||||
local errorMsg = wafdb:errmsg()
|
if ngx.ctx.ip_blocked then
|
||||||
if errorMsg then
|
local insertBlockIp = [[
|
||||||
ngx.log(ngx.ERR, "insert attack_log error ", errorMsg .. " ")
|
INSERT INTO block_ips (ip, is_block, blocking_time, req_log_id,create_date)
|
||||||
|
VALUES (:ip, :is_block, :blocking_time, :req_log_id, DATETIME('now'))
|
||||||
|
]]
|
||||||
|
stmt = wafdb:prepare(insertBlockIp)
|
||||||
|
stmt:bind_names {
|
||||||
|
ip=real_ip,
|
||||||
|
is_block = is_block,
|
||||||
|
blocking_time = blocking_time or 0,
|
||||||
|
req_log_id = log_id
|
||||||
|
}
|
||||||
|
code2 = stmt:step()
|
||||||
|
stmt:finalize()
|
||||||
|
end
|
||||||
|
|
||||||
|
wafdb:execute([[COMMIT]])
|
||||||
|
|
||||||
|
if code ~= 101 or code2 ~= 101 then
|
||||||
|
local error_msg = wafdb:errmsg()
|
||||||
|
if error_msg then
|
||||||
|
ngx.log(ngx.ERR, "insert attack_log error ", error_msg .. " ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -176,7 +201,13 @@ local function count_not_found()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function count_req_status(wafdb,is_attack)
|
local function count_req_status(is_attack)
|
||||||
|
local wafdb = utils.get_wafdb(config.waf_db_path)
|
||||||
|
if not wafdb then
|
||||||
|
ngx.log(ngx.ERR, "get log db failed")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local today = ngx.today()
|
local today = ngx.today()
|
||||||
local status = ngx.status
|
local status = ngx.status
|
||||||
|
|
||||||
|
|
@ -184,7 +215,8 @@ local function count_req_status(wafdb,is_attack)
|
||||||
stmt_exist:bind_values(today)
|
stmt_exist:bind_values(today)
|
||||||
stmt_exist:step()
|
stmt_exist:step()
|
||||||
local count = stmt_exist:get_uvalues()
|
local count = stmt_exist:get_uvalues()
|
||||||
|
stmt_exist:finalize()
|
||||||
|
|
||||||
local req_count_update = 1
|
local req_count_update = 1
|
||||||
local count_4xx_update = (status >= 400 and status < 500) and 1 or 0
|
local count_4xx_update = (status >= 400 and status < 500) and 1 or 0
|
||||||
local count_5xx_update = (status >= 500) and 1 or 0
|
local count_5xx_update = (status >= 500) and 1 or 0
|
||||||
|
|
@ -204,9 +236,9 @@ local function count_req_status(wafdb,is_attack)
|
||||||
end
|
end
|
||||||
|
|
||||||
if code ~= 101 then
|
if code ~= 101 then
|
||||||
local errorMsg = wafdb:errmsg()
|
local error_msg = wafdb:errmsg()
|
||||||
if errorMsg then
|
if error_msg then
|
||||||
ngx.log(ngx.ERR, "update waf_stat error ", errorMsg .. " ")
|
ngx.log(ngx.ERR, "update waf_stat error ", error_msg .. " ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -217,17 +249,13 @@ if config.is_waf_on() then
|
||||||
|
|
||||||
if not ngx.ctx.ip then
|
if not ngx.ctx.ip then
|
||||||
ngx.ctx.ip = utils.get_real_ip()
|
ngx.ctx.ip = utils.get_real_ip()
|
||||||
ngx.ctx.geoip = utils.get_geo_ip(ngx.ctx.ip)
|
ngx.ctx.ip_location = utils.get_ip_location(ngx.ctx.ip)
|
||||||
local ua = utils.get_header("user-agent")
|
local ua = utils.get_header("user-agent")
|
||||||
if not ua then
|
if not ua then
|
||||||
ua = ""
|
ua = ""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
count_req_status(is_attack)
|
||||||
local wafdb = utils.get_wafdb(config.waf_db_path)
|
write_req_log(is_attack)
|
||||||
if wafdb ~= nil then
|
|
||||||
count_req_status(wafdb,is_attack)
|
|
||||||
write_req_log(wafdb,is_attack)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,87 +2,144 @@
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "select.+(from|limit)"
|
"name": "sqlInject1",
|
||||||
|
"rule": "select.+(from|limit)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:(union(.*?)select))"
|
"name": "sqlInject2",
|
||||||
|
"rule": "(?:(union(.*?)select))",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "having|rongjitest"
|
"name": "sqlInject3",
|
||||||
|
"rule": "having|rongjitest",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "sleep\\((\\s*)(\\d*)(\\s*)\\)"
|
"name": "sqlInject4",
|
||||||
|
"rule": "sleep\\((\\s*)(\\d*)(\\s*)\\)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "benchmark\\((.*)\\,(.*)\\)"
|
"name": "sqlInject5",
|
||||||
|
"rule": "benchmark\\((.*)\\,(.*)\\)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:from\\W+information_schema\\W)"
|
"name": "sqlInject6",
|
||||||
|
"rule": "group\\s+by.+\\(",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:(?:current_)user|database|schema|connection_id)\\s*\\("
|
"name": "sqlInject7",
|
||||||
|
"rule": "(?:from\\W+information_schema\\W)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:etc\\/\\W*passwd)"
|
"name": "sqlInject8",
|
||||||
|
"rule": "(?:(?:current_)user|database|schema|connection_id)\\s*\\(",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "into(\\s+)+(?:dump|out)file\\s*"
|
"name": "sqlInject9",
|
||||||
|
"rule": "into(\\s+)+(?:dump|out)file\\s*",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "group\\s+by.+\\("
|
"name": "sqlInject10",
|
||||||
|
"rule": "\\s+(or|xor|and)\\s+.*(=|<|>|'|\")",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "xwork.MethodAccessor"
|
"name": "args1",
|
||||||
|
"rule": "xwork.MethodAccessor",
|
||||||
|
"type": "args",
|
||||||
|
"description": "Struts 恶意参数过滤"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?: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)\\("
|
"name": "args2",
|
||||||
|
"rule": "xwork\\.MethodAccessor",
|
||||||
|
"type": "args",
|
||||||
|
"description": "Struts 恶意参数过滤"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "xwork\\.MethodAccessor"
|
"name": "oneWordTrojan1",
|
||||||
|
"rule": "(?: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)\\(",
|
||||||
|
"type": "oneWordTrojan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\\:\\/"
|
"name": "oneWordTrojan2",
|
||||||
|
"rule": "\\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\\[",
|
||||||
|
"type": "oneWordTrojan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "java\\.lang"
|
"name": "protocolFilter1",
|
||||||
|
"rule": "(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\\:\\/",
|
||||||
|
"type": "protocolFilter",
|
||||||
|
"description": "协议过滤"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "\\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\\["
|
"name": "dirFilter1",
|
||||||
|
"rule": "(?:etc\\/\\W*passwd)",
|
||||||
|
"type": "dirFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "\\<(iframe|script|body|img|layer|div|meta|style|base|object|input)"
|
"name": "dirFilter2",
|
||||||
|
"rule": "java\\.lang",
|
||||||
|
"type": "dirFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(onmouseover|onerror|onload)\\="
|
"name": "xss1",
|
||||||
|
"rule": "\\<(iframe|script|body|img|layer|div|meta|style|base|object|input)",
|
||||||
|
"type": "xss"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "/shell?cd+/tmp;\\s*rm+-rf\\+\\*;\\s*wget"
|
"name": "xss2",
|
||||||
|
"rule": "(onmouseover|onerror|onload)\\=",
|
||||||
|
"type": "xss"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "/systembc/password.php"
|
"name": "xss3",
|
||||||
|
"rule": "base64_decode\\(",
|
||||||
|
"type": "xss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "webshell1",
|
||||||
|
"rule": "/shell?cd+/tmp;\\s*rm+-rf\\+\\*;\\s*wget",
|
||||||
|
"type": "webshell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "phpExec1",
|
||||||
|
"rule": "/systembc/password.php",
|
||||||
|
"type": "phpExec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state":"on",
|
"state":"on",
|
||||||
"rule":"(Acunetix-Aspect|Acunetix-Aspect-Password|Acunetix-Aspect-Queries|X-WIPP|X-RequestManager-Memo|X-Request-Memo|X-Scan-Memo)"
|
"name": "scannerFilter1",
|
||||||
|
"rule":"(Acunetix-Aspect|Acunetix-Aspect-Password|Acunetix-Aspect-Queries|X-WIPP|X-RequestManager-Memo|X-Request-Memo|X-Scan-Memo)",
|
||||||
|
"type": "scannerFilter"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -2,87 +2,137 @@
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "\\.\\./"
|
"name": "dirFilter1",
|
||||||
|
"rule": "\\.\\./",
|
||||||
|
"type": "dirFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "\\:\\$"
|
"name": "dirFilter2",
|
||||||
|
"rule": "\\:\\$",
|
||||||
|
"type": "dirFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "\\$\\{"
|
"name": "dirFilter3",
|
||||||
|
"rule": "\\$\\{",
|
||||||
|
"type": "dirFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "select.+(from|limit)"
|
"name": "dirFilter4",
|
||||||
|
"rule": "(?:etc\\/\\W*passwd)",
|
||||||
|
"type": "dirFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:(union(.*?)select))"
|
"name": "dirFilter5",
|
||||||
|
"rule": "java\\.lang",
|
||||||
|
"type": "dirFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "having|rongjitest"
|
"name": "sqlInject1",
|
||||||
|
"rule": "select.+(from|limit)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "sleep\\((\\s*)(\\d*)(\\s*)\\)"
|
"name": "sqlInject2",
|
||||||
|
"rule": "(?:(union(.*?)select))",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "benchmark\\((.*)\\,(.*)\\)"
|
"name": "sqlInject3",
|
||||||
|
"rule": "having|rongjitest",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "base64_decode\\("
|
"name": "sqlInject4",
|
||||||
|
"rule": "sleep\\((\\s*)(\\d*)(\\s*)\\)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:from\\W+information_schema\\W)"
|
"name": "sqlInject5",
|
||||||
|
"rule": "benchmark\\((.*)\\,(.*)\\)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:(?:current_)user|database|schema|connection_id)\\s*\\("
|
"name": "sqlInject6",
|
||||||
|
"rule": "group\\s+by.+\\(",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?:etc\\/\\W*passwd)"
|
"name": "sqlInject7",
|
||||||
|
"rule": "(?:from\\W+information_schema\\W)",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "into(\\s+)+(?:dump|out)file\\s*"
|
"name": "sqlInject8",
|
||||||
|
"rule": "(?:(?:current_)user|database|schema|connection_id)\\s*\\(",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "group\\s+by.+\\("
|
"name": "sqlInject9",
|
||||||
|
"rule": "into(\\s+)+(?:dump|out)file\\s*",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "xwork.MethodAccessor"
|
"name": "sqlInject10",
|
||||||
|
"rule": "\\s+(or|xor|and)\\s+.*(=|<|>|'|\")",
|
||||||
|
"type": "sqlInject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(?: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)\\("
|
"name": "args1",
|
||||||
|
"rule": "xwork.MethodAccessor",
|
||||||
|
"type": "args",
|
||||||
|
"description": "Struts 恶意参数过滤"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "xwork\\.MethodAccessor"
|
"name": "args2",
|
||||||
|
"rule": "xwork\\.MethodAccessor",
|
||||||
|
"type": "args",
|
||||||
|
"description": "Struts 恶意参数过滤"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\\:\\/"
|
"name": "oneWordTrojan1",
|
||||||
|
"rule": "(?: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)\\(",
|
||||||
|
"type": "oneWordTrojan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "java\\.lang"
|
"name": "oneWordTrojan2",
|
||||||
|
"rule": "\\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\\[",
|
||||||
|
"type": "oneWordTrojan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "\\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\\["
|
"name": "protocolFilter1",
|
||||||
|
"rule": "(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\\:\\/",
|
||||||
|
"type": "protocolFilter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state":"on",
|
"state":"on",
|
||||||
"rule":"(CustomCookie|acunetixCookie)"
|
"name":"scannerFilter1",
|
||||||
|
"rule":"(CustomCookie|acunetixCookie)",
|
||||||
|
"type": "scannerFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "xss1",
|
||||||
|
"rule": "base64_decode\\(",
|
||||||
|
"type": "xss"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,16 +1,10 @@
|
||||||
{
|
{
|
||||||
"nextId": 3,
|
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"type": "defaultUABlack",
|
"name": "uaBlock1",
|
||||||
"action": "deny",
|
|
||||||
"rule": "HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/",
|
"rule": "HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/",
|
||||||
"ipBlock": "on",
|
"type": "scannerFilter"
|
||||||
"ipBlockTimeout": 600,
|
|
||||||
"code": 403,
|
|
||||||
"description": "一些不友好ua"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
82
plugins/openresty/waf/rules/defaultUrlBlack.json
Normal file
82
plugins/openresty/waf/rules/defaultUrlBlack.json
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
{
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "\\.(htaccess|mysql_history|bash_history|DS_Store|idea|user\\.ini)",
|
||||||
|
"name": "dirFilter1",
|
||||||
|
"type": "dirFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "\\.(bak|inc|old|mdb|sql|backup|java|class)$",
|
||||||
|
"name": "dirFilter2",
|
||||||
|
"type": "dirFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "^/(vhost|bbs|host|wwwroot|www|site|root|backup|data|ftp|db|admin|website|web).*\\.(rar|sql|zip|tar\\.gz|tar)$",
|
||||||
|
"name": "dirFilter3",
|
||||||
|
"type": "dirFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "java\\.lang",
|
||||||
|
"name": "dirFilter4",
|
||||||
|
"type": "dirFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "/(hack|shell|spy|phpspy)\\.php$",
|
||||||
|
"name": "phpExec1",
|
||||||
|
"type": "phpExec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\\\\w+).(php|jsp)",
|
||||||
|
"name": "phpExec2",
|
||||||
|
"type": "phpExec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "(?:phpMyAdmin2|phpMyAdmin|phpmyadmin|dbadmin|pma|myadmin|admin|mysql)/scripts/setup%.php",
|
||||||
|
"name": "phpExec3",
|
||||||
|
"type": "phpExec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "(?: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)\\(",
|
||||||
|
"name": "oneWordTrojan1",
|
||||||
|
"type": "oneWordTrojan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "(phpmyadmin|jmx-console|jmxinvokerservlet)",
|
||||||
|
"name": "appFilter1",
|
||||||
|
"type": "appFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "wp-includes/wlwmanifest.xml",
|
||||||
|
"name": "appFilter2",
|
||||||
|
"type": "appFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "<php>die(@md5(HelloThinkCMF))</php>",
|
||||||
|
"name": "appFilter3",
|
||||||
|
"type": "appFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "/boaform/admin/formLogin",
|
||||||
|
"name": "appFilter4",
|
||||||
|
"type": "appFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"rule": "(?:(union(.*?)select))",
|
||||||
|
"name": "sqlInject1",
|
||||||
|
"type": "sqlInject"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,22 @@
|
||||||
{
|
{
|
||||||
"rules":[
|
"rules": [
|
||||||
{"state":"on","rule":"/TomcatBypass/Command/Base64"},
|
{
|
||||||
{"state":"on","rule":"j\\S*ndi\\S*:\\S*(?:dap|dns)\\S+"},
|
"state": "on",
|
||||||
{"state":"on","rule":"(/acunetix-wvs-test-for-some-inexistent-file|netsparker|acunetix_wvs_security_test|AppScan|XSS@HERE)"}
|
"name": "appFilter1",
|
||||||
|
"rule": "/TomcatBypass/Command/Base64",
|
||||||
|
"type": "appFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "appFilter2",
|
||||||
|
"rule": "j\\S*ndi\\S*:\\S*(?:dap|dns)\\S+",
|
||||||
|
"type": "appFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "scannerFilter1",
|
||||||
|
"rule": "(/acunetix-wvs-test-for-some-inexistent-file|netsparker|acunetix_wvs_security_test|AppScan|XSS@HERE)",
|
||||||
|
"type": "scannerFilter"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,23 @@
|
||||||
"name": "拦截IP",
|
"name": "拦截IP",
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"type": "ipv4",
|
"type": "ipv4",
|
||||||
"ipv4": "123"
|
"ipv4": "123",
|
||||||
|
"description": "拦截IP"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "拦截IP",
|
||||||
|
"state": "on",
|
||||||
|
"type": "ipv6",
|
||||||
|
"ipv6": "kjdhsakjdhsakjdhakshd",
|
||||||
|
"description": "拦截IP"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "拦截IP",
|
||||||
|
"state": "on",
|
||||||
|
"type": "ipArr",
|
||||||
|
"ipStart": "192.168.1.1",
|
||||||
|
"ipEnd": "192.168.1.10",
|
||||||
|
"description": "拦截IP"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,87 +2,129 @@
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "GET"
|
"rule": "GET",
|
||||||
|
"name": "GET",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "POST"
|
"rule": "POST",
|
||||||
|
"name": "POST",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "PUT"
|
"rule": "PUT",
|
||||||
|
"name": "PUT",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "DELETE"
|
"rule": "DELETE",
|
||||||
|
"name": "DELETE",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "PATCH"
|
"rule": "PATCH",
|
||||||
|
"name": "PATCH",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "HEAD"
|
"rule": "HEAD",
|
||||||
|
"name": "HEAD",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "OPTIONS"
|
"rule": "OPTIONS",
|
||||||
|
"name": "OPTIONS",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "TRACE"
|
"rule": "TRACE",
|
||||||
|
"name": "TRACE",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "CONNECT"
|
"rule": "CONNECT",
|
||||||
|
"name": "CONNECT",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "PROPFIND"
|
"rule": "PROPFIND",
|
||||||
|
"name": "PROPFIND",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "PROPPATCH"
|
"rule": "PROPPATCH",
|
||||||
|
"name": "PROPPATCH",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "MKCOL"
|
"rule": "MKCOL",
|
||||||
|
"name": "MKCOL",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "COPY"
|
"rule": "COPY",
|
||||||
|
"name": "COPY",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "MOVE"
|
"rule": "MOVE",
|
||||||
|
"name": "MOVE",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "LOCK"
|
"rule": "LOCK",
|
||||||
|
"name": "LOCK",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "UNLOCK"
|
"rule": "UNLOCK",
|
||||||
|
"name": "UNLOCK",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "LINK"
|
"rule": "LINK",
|
||||||
|
"name": "LINK",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "UNLINK"
|
"rule": "UNLINK",
|
||||||
|
"name": "UNLINK",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "WRAPPED"
|
"rule": "WRAPPED",
|
||||||
|
"name": "WRAPPED",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "PROPFIND"
|
"rule": "PROPFIND",
|
||||||
|
"name": "PROPFIND",
|
||||||
|
"type": "httpMethod"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state": "on",
|
"state": "on",
|
||||||
"rule": "SRARCH"
|
"rule": "SRARCH",
|
||||||
|
"name": "SRARCH",
|
||||||
|
"type": "httpMethod"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,121 @@
|
||||||
{
|
{
|
||||||
"rules":[
|
"rules": [
|
||||||
{"state":"on","action":"deny","rule":"select.+(from|limit)"},
|
{
|
||||||
{"state":"on","action":"deny","rule":"(?:(union(.*?)select))"},
|
"state": "on",
|
||||||
{"state":"on","action":"deny","rule":"having|rongjitest"},
|
"name": "sqlInject1",
|
||||||
{"state":"on","action":"deny","rule":"sleep\\((\\s*)(\\d*)(\\s*)\\)"},
|
"rule": "select.+(from|limit)",
|
||||||
{"state":"on","action":"deny","rule":"benchmark\\((.*)\\,(.*)\\)"},
|
"type": "sqlInject"
|
||||||
{"state":"on","action":"deny","rule":"base64_decode\\("},
|
},
|
||||||
{"state":"on","action":"deny","rule":"(?:from\\W+information_schema\\W)"},
|
{
|
||||||
{"state":"on","action":"deny","rule":"(?:(?:current_)user|database|schema|connection_id)\\s*\\("},
|
"state": "on",
|
||||||
{"state":"on","action":"deny","rule":"(?:etc\\/\\W*passwd)"},
|
"name": "sqlInject2",
|
||||||
{"state":"on","action":"deny","rule":"into(\\s+)+(?:dump|out)file\\s*"},
|
"rule": "(?:(union(.*?)select))",
|
||||||
{"state":"on","action":"deny","rule":"group\\s+by.+\\("},
|
"type": "sqlInject"
|
||||||
{"state":"on","action":"deny","rule":"xwork.MethodAccessor"},
|
},
|
||||||
{"state":"on","action":"deny","rule":"(?: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)\\("},
|
{
|
||||||
{"state":"on","action":"deny","rule":"xwork\\.MethodAccessor"},
|
"state": "on",
|
||||||
{"state":"on","action":"deny","rule":"(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\\:\\/"},
|
"name": "sqlInject3",
|
||||||
{"state":"on","action":"deny","rule":"java\\.lang"},
|
"rule": "having|rongjitest",
|
||||||
{"state":"on","action":"deny","rule":"\\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\\["},
|
"type": "sqlInject"
|
||||||
{"state":"on","action":"deny","rule":"\\<(iframe|script|body|img|layer|div|meta|style|base|object|input)"},
|
},
|
||||||
{"state":"on","action":"deny","rule":"(onmouseover|onerror|onload)\\="}
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "sqlInject4",
|
||||||
|
"rule": "sleep\\((\\s*)(\\d*)(\\s*)\\)",
|
||||||
|
"type": "sqlInject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "sqlInject5",
|
||||||
|
"rule": "benchmark\\((.*)\\,(.*)\\)",
|
||||||
|
"type": "sqlInject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "sqlInject6",
|
||||||
|
"rule": "group\\s+by.+\\(",
|
||||||
|
"type": "sqlInject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "sqlInject7",
|
||||||
|
"rule": "(?:from\\W+information_schema\\W)",
|
||||||
|
"type": "sqlInject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "sqlInject8",
|
||||||
|
"rule": "(?:(?:current_)user|database|schema|connection_id)\\s*\\(",
|
||||||
|
"type": "sqlInject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "sqlInject9",
|
||||||
|
"rule": "into(\\s+)+(?:dump|out)file\\s*",
|
||||||
|
"type": "sqlInject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "args1",
|
||||||
|
"rule": "xwork.MethodAccessor",
|
||||||
|
"type": "args",
|
||||||
|
"description": "Struts 恶意参数过滤"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "args2",
|
||||||
|
"rule": "xwork\\.MethodAccessor",
|
||||||
|
"type": "args",
|
||||||
|
"description": "Struts 恶意参数过滤"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "oneWordTrojan1",
|
||||||
|
"rule": "(?: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)\\(",
|
||||||
|
"type": "oneWordTrojan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "protocolFilter1",
|
||||||
|
"rule": "(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\\:\\/",
|
||||||
|
"type": "protocolFilter",
|
||||||
|
"description": "协议过滤"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "oneWordTrojan2",
|
||||||
|
"rule": "\\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\\[",
|
||||||
|
"type": "oneWordTrojan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "xss1",
|
||||||
|
"rule": "\\<(iframe|script|body|img|layer|div|meta|style|base|object|input)",
|
||||||
|
"type": "xss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "xss2",
|
||||||
|
"rule": "(onmouseover|onerror|onload)\\=",
|
||||||
|
"type": "xss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "xss3",
|
||||||
|
"rule": "base64_decode\\(",
|
||||||
|
"type": "xss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "dirFilter1",
|
||||||
|
"rule": "(?:etc\\/\\W*passwd)",
|
||||||
|
"type": "dirFilter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "on",
|
||||||
|
"name": "dirFilter2",
|
||||||
|
"rule": "java\\.lang",
|
||||||
|
"type": "dirFilter"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
{
|
{
|
||||||
"rules": [
|
"rules": [
|
||||||
|
{
|
||||||
|
"name": "UaBlack",
|
||||||
|
"state": "on",
|
||||||
|
"action": "deny",
|
||||||
|
"rule": "ua-blacklist",
|
||||||
|
"description": "测试"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,3 @@
|
||||||
{
|
{
|
||||||
"rules": [
|
"rules": []
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "PostmanRuntime/7.36.1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,3 @@
|
||||||
{
|
{
|
||||||
"rules": [
|
"rules": []
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "\\.(svn|htaccess|bash_history)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "\\.(bak|inc|old|mdb|sql|backup|java|class)$"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "(vhost|bbs|host|wwwroot|www|site|root|hytop|flashfxp).*\\.rar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "(phpmyadmin|jmx-console|jmxinvokerservlet)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "(?:phpMyAdmin2|phpMyAdmin|phpmyadmin|dbadmin|pma|myadmin|admin|mysql)/scripts/setup%.php"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "java\\.lang"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\\\\w+).(php|jsp)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "wp-includes/wlwmanifest.xml"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "<php>die(@md5(HelloThinkCMF))</php>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"rule": "/boaform/admin/formLogin"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,3 @@
|
||||||
{
|
{
|
||||||
"rules": [
|
"rules": []
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"action": "allow",
|
|
||||||
"rule": "/console/posts/editor"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": "on",
|
|
||||||
"action": "allow",
|
|
||||||
"rule": "/apis/api.console.halo.run/v1alpha1/posts"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
@ -53,8 +53,7 @@ local function init()
|
||||||
end
|
end
|
||||||
|
|
||||||
ngx.ctx.ua = ua
|
ngx.ctx.ua = ua
|
||||||
ngx.ctx.geoip = utils.get_geo_ip(ip)
|
ngx.ctx.ip_location = utils.get_ip_location(ip)
|
||||||
|
|
||||||
ngx.ctx.website_key = get_website_key()
|
ngx.ctx.website_key = get_website_key()
|
||||||
ngx.ctx.method = ngx.req.get_method()
|
ngx.ctx.method = ngx.req.get_method()
|
||||||
ngx.ctx.content_type = utils.get_header("content-type")
|
ngx.ctx.content_type = utils.get_header("content-type")
|
||||||
|
|
@ -132,26 +131,27 @@ if config.is_waf_on() then
|
||||||
if lib.is_white_ip() then
|
if lib.is_white_ip() then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
lib.default_ip_black()
|
|
||||||
lib.black_ip()
|
lib.black_ip()
|
||||||
|
lib.default_ip_black()
|
||||||
|
|
||||||
if lib.is_white_ua() then
|
if lib.is_white_ua() then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
lib.default_ua_black()
|
|
||||||
lib.black_ua()
|
lib.black_ua()
|
||||||
|
lib.default_ua_black()
|
||||||
|
|
||||||
lib.cc_url()
|
lib.cc_url()
|
||||||
if lib.is_white_url() then
|
if lib.is_white_url() then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
lib.black_url()
|
lib.black_url()
|
||||||
|
lib.default_url_black()
|
||||||
|
|
||||||
lib.allow_location_check()
|
lib.allow_location_check()
|
||||||
lib.acl()
|
|
||||||
lib.bot_check()
|
|
||||||
lib.method_check()
|
lib.method_check()
|
||||||
|
lib.acl()
|
||||||
lib.cc()
|
lib.cc()
|
||||||
|
lib.bot_check()
|
||||||
lib.args_check()
|
lib.args_check()
|
||||||
lib.cookie_check()
|
lib.cookie_check()
|
||||||
lib.post_check()
|
lib.post_check()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue