add v0.2.1
parent
3af50b45e3
commit
4b99b0de33
65
README.md
65
README.md
|
@ -7,7 +7,7 @@ ngx_lua_waf是我刚入职趣游时候开发的一个基于ngx_lua的web应用
|
|||
现在开源出来.其中包含我们的过滤规则。如果大家有什么建议和想fa,欢迎和我一起完善。
|
||||
|
||||
###用途:
|
||||
|
||||
|
||||
防止sql注入,本地包含,部分溢出,fuzzing测试,xss,SSRF等web攻击
|
||||
防止svn/备份之类文件泄漏
|
||||
防止ApacheBench之类压力测试工具的攻击
|
||||
|
@ -18,29 +18,60 @@ ngx_lua_waf是我刚入职趣游时候开发的一个基于ngx_lua的web应用
|
|||
|
||||
###效果图如下:
|
||||
|
||||
![sec](http://www.sectop.org/wp-content/uploads/2013/03/QQ截图20130323150826.jpg)
|
||||
![sec](http://i.imgur.com/DqU30au.png)
|
||||
|
||||
###推荐安装:
|
||||
|
||||
请自行给nginx安装ngx_lua模块,需要lujit做lua支持
|
||||
|
||||
请提前新建/data/logs/hack/目录攻击日志,并赋予nginx用户对该目录的写入权限。
|
||||
请自行给nginx安装ngx_lua模块,推荐使用lujit做lua支持
|
||||
|
||||
|
||||
###配置部分:
|
||||
###使用说明:
|
||||
|
||||
编辑init.lua配置部分
|
||||
logpath='/data/logs/hack/'
|
||||
rulepath='/usr/local/nginx/conf/wafconf/'
|
||||
syslogserver='127.0.0.1'
|
||||
如果需要开启syslog传输,请取消掉log函数部分的注释
|
||||
filext是限制上传的文件后缀名
|
||||
nginx安装路径假设为:/usr/local/nginx/conf/
|
||||
|
||||
在nginx.conf的http段添加
|
||||
init_by_lua_file /usr/local/nginx/conf/init.lua;
|
||||
access_by_lua_file /usr/local/nginx/conf/waf.lua;
|
||||
|
||||
注意:第一次安装配置好需要重启nginx
|
||||
把ngx_lua_waf下载到conf目录下,解压命名为waf
|
||||
|
||||
在nginx.conf的http段添加
|
||||
|
||||
lua_package_path "/usr/local/nginx/conf/waf/?.lua";
|
||||
lua_shared_dict limit 10m;
|
||||
init_by_lua_file /usr/local/nginx/conf/waf/init.lua;
|
||||
access_by_lua_file /usr/local/nginx/conf/waf/waf.lua;
|
||||
|
||||
配置config.lua里的waf规则目录(一般在waf/conf/目录下)
|
||||
|
||||
RulePath = "/usr/local/nginx/conf/waf/wafconf/"
|
||||
|
||||
绝对路径如有变动,需对应修改
|
||||
|
||||
###配置文件详细说明:
|
||||
|
||||
RulePath = "/usr/local/nginx/conf/waf/wafconf/"
|
||||
--规则存放目录
|
||||
attacklog = "off"
|
||||
--是否开启攻击信息记录,需要配置logdir
|
||||
logdir = "/usr/local/nginx/logs/hack/"
|
||||
--log存储目录,该目录需要nginx用户的可写权限
|
||||
UrlDeny="on"
|
||||
--是否拦截url访问
|
||||
Redirect="on"
|
||||
--是否拦截后重定向
|
||||
CookieMatch = "on"
|
||||
--是否拦截cookie攻击
|
||||
postMatch = "on"
|
||||
--是否拦截post攻击
|
||||
whiteModule = "on"
|
||||
--是否开启白名单
|
||||
ipWhitelist={"127.0.0.1"}
|
||||
--ip白名单,多个ip用逗号分隔
|
||||
CCDeny="on"
|
||||
--是否开启拦截cc攻击(需要nginx.conf的http段增加lua_shared_dict limit 10m;)
|
||||
CCrate = "100/60"
|
||||
--设置cc攻击频率,单位为秒.
|
||||
--默认1分钟同一个IP只能请求同一个文件(request_filename)100次
|
||||
html=[[Please go away~~]]
|
||||
--警告内容,可在中括号内自定义
|
||||
备注:不要乱动双引号,区分大小写
|
||||
|
||||
###规则更新:
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
RulePath = "/usr/local/nginx/conf/waf/wafconf/"
|
||||
attacklog = "off"
|
||||
logdir = "/usr/local/nginx/logs/hack/"
|
||||
UrlDeny="on"
|
||||
Redirect="on"
|
||||
CookieMatch="on"
|
||||
postMatch="on"
|
||||
whiteModule="on"
|
||||
ipWhitelist={"127.0.0.1"}
|
||||
CCDeny="off"
|
||||
CCrate="100/60"
|
||||
html=[[Please go away~~ ]]
|
260
init.lua
260
init.lua
|
@ -1,67 +1,52 @@
|
|||
--配置部分
|
||||
logpath='/data/logs/hack/'
|
||||
rulepath='/usr/local/nginx/conf/wafconf/'
|
||||
syslogserver='127.0.0.1'
|
||||
filext=''
|
||||
--如果需要开启syslog传输,请取消掉log函数部分的注释
|
||||
--syslog函数和本地日志记录函数
|
||||
local bit = require "bit"
|
||||
local ffi = require "ffi"
|
||||
local C = ffi.C
|
||||
local bor = bit.bor
|
||||
ffi.cdef[[
|
||||
int write(int fd, const char *buf, int nbyte);
|
||||
int open(const char *path, int access, int mode);
|
||||
int close(int fd);
|
||||
]]
|
||||
|
||||
local O_RDWR = 0X0002;
|
||||
local O_CREAT = 0x0040;
|
||||
local O_APPEND = 0x0400;
|
||||
local S_IRUSR = 0x0100;
|
||||
local S_IWUSR = 0x0080;
|
||||
function write(logfile,msg)
|
||||
local logger_fd = C.open(logfile, bor(O_RDWR, O_CREAT, O_APPEND), bor(S_IRUSR,S_IWUSR));
|
||||
local c = msg;
|
||||
C.write(logger_fd, c, #c);
|
||||
C.close(logger_fd)
|
||||
end
|
||||
function syslog(msg)
|
||||
ngx.header.content_type = "text/html"
|
||||
local sock = ngx.socket.udp()
|
||||
local ok, err = sock:setpeername(syslogserver, 514)
|
||||
--上面的ip和端口就是syslog server的ip和端口地址,可自行修改
|
||||
if not ok then
|
||||
ngx.say("failed to connect to syslog server: ", err)
|
||||
return
|
||||
end
|
||||
ok, err = sock:send('<30>'..msg)
|
||||
sock:close()
|
||||
end
|
||||
function log(method,url,data)
|
||||
if data then
|
||||
if ngx.var.http_user_agent then
|
||||
-- syslog(ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \""..data.."\" \""..ngx.status.."\" \""..ngx.var.http_user_agent.."\"\n")
|
||||
write(logpath..'/'..ngx.var.server_name.."_sec.log",ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \""..data.."\" \""..ngx.status.."\" \""..ngx.var.http_user_agent.."\"\n")
|
||||
else
|
||||
-- syslog(ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \""..data.."\" \"-\"\n")
|
||||
write(logpath..'/'..ngx.var.server_name.."_sec.log",ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \""..data.."\" \"-\"\n")
|
||||
end
|
||||
else
|
||||
if ngx.var.http_user_agent then
|
||||
-- syslog(ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \"-\" \""..ngx.var.http_user_agent.."\"\n")
|
||||
write(logpath..'/'..ngx.var.server_name.."_sec.log",ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \"-\" \""..ngx.var.http_user_agent.."\"\n")
|
||||
else
|
||||
-- syslog(ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \"-\" \"".."-\"\n")
|
||||
write(logpath..'/'..ngx.var.server_name.."_sec.log",ngx.var.remote_addr.." ".." ["..ngx.localtime().."] \""..method.." "..url.."\" \"-\" \"".."-\"\n")
|
||||
require 'config'
|
||||
local match = string.match
|
||||
local ngxmatch=ngx.re.match
|
||||
local unescape=ngx.unescape_uri
|
||||
local get_headers = ngx.req.get_headers
|
||||
local optionIsOn = function (options) return options == "on" and true or false end
|
||||
logpath = logdir
|
||||
rulepath = RulePath
|
||||
UrlDeny = optionIsOn(UrlDeny)
|
||||
PostCheck = optionIsOn(postMatch)
|
||||
CookieCheck = optionIsOn(cookieMatch)
|
||||
WhiteCheck = optionIsOn(whiteModule)
|
||||
PathInfoFix = optionIsOn(PathInfoFix)
|
||||
attacklog = optionIsOn(attacklog)
|
||||
CCDeny = optionIsOn(CCDeny)
|
||||
CCrate = CCrate
|
||||
Redirect=optionIsOn(Redirect)
|
||||
ipWhitelist=ipWhitelist
|
||||
function getClientIp()
|
||||
IP = ngx.req.get_headers()["X-Real-IP"]
|
||||
if IP == nil then
|
||||
IP = ngx.var.remote_addr
|
||||
end
|
||||
end
|
||||
if IP == nil then
|
||||
IP = "unknown"
|
||||
end
|
||||
return IP
|
||||
end
|
||||
--------------------------------------响应函数--------------------------------------------------------------------------------
|
||||
function check()
|
||||
ngx.header.content_type = "text/html"
|
||||
ngx.print("just a joke hehe~ !!")
|
||||
ngx.exit(200)
|
||||
function write(logfile,msg)
|
||||
local fd = io.open(logfile,"ab")
|
||||
if fd == nil then return end
|
||||
fd:write(msg)
|
||||
fd:flush()
|
||||
fd:close()
|
||||
end
|
||||
function log(method,url,data,ruletag)
|
||||
if attacklog then
|
||||
local realIp = getClientIp()
|
||||
local ua = ngx.var.http_user_agent
|
||||
local servername=ngx.var.server_name
|
||||
local time=ngx.localtime()
|
||||
if ua then
|
||||
line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..ruletag.."\"\n"
|
||||
else
|
||||
line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n"
|
||||
end
|
||||
local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log"
|
||||
write(filename,line)
|
||||
end
|
||||
end
|
||||
------------------------------------规则读取函数-------------------------------------------------------------------
|
||||
function read_rule(var)
|
||||
|
@ -71,10 +56,149 @@ function read_rule(var)
|
|||
table.insert(t,line)
|
||||
end
|
||||
file:close()
|
||||
return(table.concat(t,"|"))
|
||||
return(t)
|
||||
end
|
||||
|
||||
urlrules=read_rule('url')
|
||||
argsrules=read_rule('args')
|
||||
uarules=read_rule('user-agent')
|
||||
wturlrules=read_rule('whiteurl')
|
||||
postrules=read_rule('post')
|
||||
ckrules=read_rule('cookie')
|
||||
|
||||
|
||||
function say_html()
|
||||
if Redirect then
|
||||
ngx.header.content_type = "text/html"
|
||||
ngx.say(html)
|
||||
ngx.exit(200)
|
||||
end
|
||||
end
|
||||
|
||||
function whiteurl()
|
||||
if WhiteCheck then
|
||||
for _,rule in pairs(wturlrules) do
|
||||
if ngxmatch(ngx.var.request_uri,rule,"isjo") then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function args()
|
||||
for _,rule in pairs(argsrules) do
|
||||
local args = ngx.req.get_uri_args()
|
||||
for key, val in pairs(args) do
|
||||
if type(val)=='table' then
|
||||
data=table.concat(val, " ")
|
||||
else
|
||||
data=val
|
||||
end
|
||||
if data and type(data) ~= "boolean" and ngxmatch(unescape(data),rule,"isjo") then
|
||||
log('GET',ngx.var.request_uri,"-",rule)
|
||||
say_html()
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function url()
|
||||
if UrlDeny then
|
||||
for _,rule in pairs(urlrules) do
|
||||
if ngxmatch(ngx.var.request_uri,rule,"isjo") then
|
||||
log('GET',ngx.var.request_uri,"-",rule)
|
||||
say_html()
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ua()
|
||||
local ua = ngx.var.http_user_agent
|
||||
for _,rule in pairs(uarules) do
|
||||
if ngxmatch(ua,rule,"isjo") then
|
||||
log('UA',ngx.var.request_uri,"-",rule)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
function body(data)
|
||||
for _,rule in pairs(postrules) do
|
||||
if ngxmatch(unescape(data),rule,"isjo") then
|
||||
log('POST',ngx.var.request_uri,data,rule)
|
||||
say_html()
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
function cookie()
|
||||
local ck = ngx.var.http_cookie
|
||||
if CookieCheck and ck then
|
||||
for _,rule in pairs(ckrules) do
|
||||
if ngxmatch(ck,rule,"isjo") then
|
||||
log('Cookie',ngx.var.request_uri,"-",rule)
|
||||
say_html()
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function denycc()
|
||||
if CCDeny then
|
||||
CCcount=tonumber(string.match(CCrate,'(.*)/'))
|
||||
CCseconds=tonumber(string.match(CCrate,'/(.*)'))
|
||||
local token=getClientIp()..ngx.var.request_filename
|
||||
local limit = ngx.shared.limit
|
||||
local req,_=limit:get(token)
|
||||
if req then
|
||||
if req > CCcount then
|
||||
ngx.exit(503)
|
||||
return true
|
||||
else
|
||||
limit:incr(token,1)
|
||||
end
|
||||
else
|
||||
limit:set(token,1,CCseconds)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function get_boundary()
|
||||
local header = get_headers()["content-type"]
|
||||
if not header then
|
||||
return nil
|
||||
end
|
||||
|
||||
if type(header) == "table" then
|
||||
header = header[1]
|
||||
end
|
||||
|
||||
local m = match(header, ";%s*boundary=\"([^\"]+)\"")
|
||||
if m then
|
||||
return m
|
||||
end
|
||||
|
||||
return match(header, ";%s*boundary=([^\",;]+)")
|
||||
end
|
||||
|
||||
function whiteip()
|
||||
if next(ipWhitelist) ~= nil then
|
||||
for _,ip in pairs(ipWhitelist) do
|
||||
if getClientIp()==ip then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
regex=read_rule('global')
|
||||
get=read_rule('get')
|
||||
post=read_rule('post')
|
||||
agent=read_rule('user-agent')
|
||||
whitelist=read_rule('whitelist')
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local sub = string.sub
|
||||
local req_socket = ngx.req.socket
|
||||
local null = ngx.null
|
||||
local match = string.match
|
||||
local setmetatable = setmetatable
|
||||
local error = error
|
||||
local get_headers = ngx.req.get_headers
|
||||
local type = type
|
||||
local print = print
|
||||
|
||||
|
||||
local _M = { _VERSION = '0.08' }
|
||||
|
||||
|
||||
local MAX_LINE_SIZE = 512
|
||||
|
||||
local STATE_BEGIN = 1
|
||||
local STATE_READING_HEADER = 2
|
||||
local STATE_READING_BODY = 3
|
||||
local STATE_EOF = 4
|
||||
|
||||
|
||||
local mt = { __index = _M }
|
||||
|
||||
local state_handlers
|
||||
|
||||
|
||||
local function get_boundary()
|
||||
local header = get_headers()["content-type"]
|
||||
if not header then
|
||||
return nil
|
||||
end
|
||||
|
||||
if type(header) == "table" then
|
||||
header = header[1]
|
||||
end
|
||||
|
||||
local m = match(header, ";%s*boundary=\"([^\"]+)\"")
|
||||
if m then
|
||||
return m
|
||||
end
|
||||
|
||||
return match(header, ";%s*boundary=([^\",;]+)")
|
||||
end
|
||||
|
||||
|
||||
function _M.new(self, chunk_size)
|
||||
local boundary = get_boundary()
|
||||
|
||||
print("boundary: ", boundary)
|
||||
|
||||
if not boundary then
|
||||
return nil, "no boundary defined in Content-Type"
|
||||
end
|
||||
|
||||
print('boundary: "', boundary, '"')
|
||||
|
||||
local sock, err = req_socket()
|
||||
if not sock then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local read2boundary, err = sock:receiveuntil("--" .. boundary)
|
||||
if not read2boundary then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local read_line, err = sock:receiveuntil("\r\n")
|
||||
if not read_line then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
return setmetatable({
|
||||
sock = sock,
|
||||
size = chunk_size or 4096,
|
||||
read2boundary = read2boundary,
|
||||
read_line = read_line,
|
||||
boundary = boundary,
|
||||
state = STATE_BEGIN
|
||||
}, mt)
|
||||
end
|
||||
|
||||
|
||||
function _M.set_timeout(self, timeout)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, "not initialized"
|
||||
end
|
||||
|
||||
return sock:settimeout(timeout)
|
||||
end
|
||||
|
||||
|
||||
local function discard_line(self)
|
||||
local read_line = self.read_line
|
||||
|
||||
local line, err = self.read_line(MAX_LINE_SIZE)
|
||||
if not line then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local dummy, err = self.read_line(1)
|
||||
if dummy then
|
||||
return nil, "line too long: " .. line .. dummy .. "..."
|
||||
end
|
||||
|
||||
if err then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
local function discard_rest(self)
|
||||
local sock = self.sock
|
||||
local size = self.size
|
||||
|
||||
while true do
|
||||
local dummy, err = sock:receive(size)
|
||||
if err and err ~= 'closed' then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
if not dummy then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function read_body_part(self)
|
||||
local read2boundary = self.read2boundary
|
||||
|
||||
local chunk, err = read2boundary(self.size)
|
||||
if err then
|
||||
return nil, nil, err
|
||||
end
|
||||
|
||||
if not chunk then
|
||||
local sock = self.sock
|
||||
|
||||
local data = sock:receive(2)
|
||||
if data == "--" then
|
||||
local ok, err = discard_rest(self)
|
||||
if not ok then
|
||||
return nil, nil, err
|
||||
end
|
||||
|
||||
self.state = STATE_EOF
|
||||
return "part_end"
|
||||
end
|
||||
|
||||
if data ~= "\r\n" then
|
||||
local ok, err = discard_line(self)
|
||||
if not ok then
|
||||
return nil, nil, err
|
||||
end
|
||||
end
|
||||
|
||||
self.state = STATE_READING_HEADER
|
||||
return "part_end"
|
||||
end
|
||||
|
||||
return "body", chunk
|
||||
end
|
||||
|
||||
|
||||
local function read_header(self)
|
||||
local read_line = self.read_line
|
||||
|
||||
local line, err = read_line(MAX_LINE_SIZE)
|
||||
if err then
|
||||
return nil, nil, err
|
||||
end
|
||||
|
||||
local dummy, err = read_line(1)
|
||||
if dummy then
|
||||
return nil, nil, "line too long: " .. line .. dummy .. "..."
|
||||
end
|
||||
|
||||
if err then
|
||||
return nil, nil, err
|
||||
end
|
||||
|
||||
-- print("read line: ", line)
|
||||
|
||||
if line == "" then
|
||||
-- after the last header
|
||||
self.state = STATE_READING_BODY
|
||||
return read_body_part(self)
|
||||
end
|
||||
|
||||
local key, value = match(line, "([^: \t]+)%s*:%s*(.+)")
|
||||
if not key then
|
||||
return 'header', line
|
||||
end
|
||||
|
||||
return 'header', {key, value, line}
|
||||
end
|
||||
|
||||
|
||||
local function eof()
|
||||
return "eof", nil
|
||||
end
|
||||
|
||||
|
||||
function _M.read(self)
|
||||
local size = self.size
|
||||
|
||||
local handler = state_handlers[self.state]
|
||||
if handler then
|
||||
return handler(self)
|
||||
end
|
||||
|
||||
return nil, nil, "bad state: " .. self.state
|
||||
end
|
||||
|
||||
|
||||
local function read_preamble(self)
|
||||
local sock = self.sock
|
||||
if not sock then
|
||||
return nil, nil, "not initialized"
|
||||
end
|
||||
|
||||
local size = self.size
|
||||
local read2boundary = self.read2boundary
|
||||
|
||||
while true do
|
||||
local preamble, err = read2boundary(size)
|
||||
if not preamble then
|
||||
break
|
||||
end
|
||||
|
||||
-- discard the preamble data chunk
|
||||
-- print("read preamble: ", preamble)
|
||||
end
|
||||
|
||||
local ok, err = discard_line(self)
|
||||
if not ok then
|
||||
return nil, nil, err
|
||||
end
|
||||
|
||||
local read2boundary, err = sock:receiveuntil("\r\n--" .. self.boundary)
|
||||
if not read2boundary then
|
||||
return nil, nil, err
|
||||
end
|
||||
|
||||
self.read2boundary = read2boundary
|
||||
|
||||
self.state = STATE_READING_HEADER
|
||||
return read_header(self)
|
||||
end
|
||||
|
||||
|
||||
state_handlers = {
|
||||
read_preamble,
|
||||
read_header,
|
||||
read_body_part,
|
||||
eof
|
||||
}
|
||||
|
||||
|
||||
return _M
|
80
waf.lua
80
waf.lua
|
@ -1,24 +1,60 @@
|
|||
ngx.req.read_body()
|
||||
if ngx.re.match(ngx.var.request_uri,whitelist,"isjo") then
|
||||
return
|
||||
else
|
||||
if ngx.re.match(ngx.unescape_uri(ngx.var.request_uri),regex.."|"..get,"isjo") then
|
||||
log('GET',ngx.unescape_uri(ngx.var.request_uri))
|
||||
check()
|
||||
elseif ngx.var.http_user_agent and ngx.re.match(ngx.var.http_user_agent,regex.."|"..agent,"isjo") then
|
||||
log('USER-AGENT',ngx.unescape_uri(ngx.var.request_uri))
|
||||
check()
|
||||
elseif ngx.req.get_body_data() and ngx.re.match(ngx.unescape_uri(ngx.req.get_body_data()),regex.."|"..post,"isjo") then
|
||||
log('POST',ngx.unescape_uri(ngx.var.request_uri),ngx.unescape_uri(ngx.req.get_body_data()))
|
||||
check()
|
||||
elseif ngx.req.get_headers()["Cookie"] and ngx.re.match(ngx.unescape_uri(ngx.req.get_headers()["Cookie"]),regex,"isjo")then
|
||||
log('COOKIE',ngx.unescape_uri(ngx.var.request_uri),ngx.unescape_uri(ngx.req.get_headers()["Cookie"]))
|
||||
check()
|
||||
elseif ngx.req.get_headers()['Acunetix-Aspect'] then
|
||||
ngx.exit(400)
|
||||
elseif ngx.req.get_headers()['X-Scan-Memo'] then
|
||||
ngx.exit(400)
|
||||
else
|
||||
return
|
||||
local upload = require "upload"
|
||||
local content_length=tonumber(ngx.req.get_headers()['content-length'])
|
||||
local method=ngx.req.get_method()
|
||||
if whiteip() then
|
||||
elseif denycc() then
|
||||
elseif ngx.var.http_Acunetix_Aspect then
|
||||
ngx.exit(444)
|
||||
elseif ngx.var.http_X_Scan_Memo then
|
||||
ngx.exit(444)
|
||||
elseif whiteurl() then
|
||||
elseif ua() then
|
||||
elseif url() then
|
||||
elseif args() then
|
||||
elseif cookie() then
|
||||
elseif PostCheck then
|
||||
if method=="POST" then
|
||||
local boundary = get_boundary()
|
||||
if boundary then
|
||||
local form = upload:new(500)
|
||||
if not form then
|
||||
return
|
||||
end
|
||||
form:set_timeout(1000) -- 1 sec
|
||||
while true do
|
||||
local typ, res, err = form:read()
|
||||
if not typ then
|
||||
return
|
||||
end
|
||||
if typ=="body" then
|
||||
body(res)
|
||||
end
|
||||
|
||||
if typ == "eof" then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- local typ, res, err = form:read()
|
||||
-- body(res)
|
||||
else
|
||||
ngx.req.read_body()
|
||||
local args = ngx.req.get_post_args()
|
||||
if not args then
|
||||
return
|
||||
end
|
||||
for key, val in pairs(args) do
|
||||
if type(val) == "table" then
|
||||
data=table.concat(val, ", ")
|
||||
else
|
||||
data=val
|
||||
end
|
||||
if data and type(data) ~= "boolean" and body(data) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
|
|
|
@ -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)\[
|
|
@ -37,6 +37,16 @@ phpinfo\(
|
|||
(?:\b(?:\.(?:ht(?:access|passwd|group)|www_?acl)|global\.asa|httpd\.conf|boot\.ini)\b|\/etc\/)
|
||||
(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data|expect)\:\/
|
||||
\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[
|
||||
java\.lang\.Process
|
||||
java\.io\.File
|
||||
\/proc\/(\d+|self)\/environ
|
||||
\<(iframe|script|body|img)
|
||||
javascript\:
|
||||
onmouseover\=
|
||||
ewebe
|
||||
jmx-console
|
||||
javascript\:
|
||||
phpmyadmin
|
||||
\$\{
|
||||
java\.lang
|
||||
\)\.exec\(
|
||||
\(\'
|
||||
\"\=
|
||||
|
|
21
wafconf/post
21
wafconf/post
|
@ -1 +1,20 @@
|
|||
\)\.exec\(
|
||||
\.\./
|
||||
\:\$
|
||||
\$\{
|
||||
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,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)
|
|
@ -1 +1 @@
|
|||
.*(LWP::Simple|winhttp|clshttp|HTTrack|harvest|nsauditor|dirbuster|pangolin|nmap|sqlninja|grendel-scan|hydra|perl|HTMLParser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|sae|zmeu|BabyKrokodil|python|netsparker|httperf|ApacheBench|webbench).*
|
||||
(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 @@
|
|||
/123/
|
Loading…
Reference in New Issue