local upload={}
local multipart=require "multipart"
local bt_engine =require "bt_engine"
local php_engine =require "php_engine"
function upload.gusb_string(table)
local ret={"-","]","@","#","&","_","{","}"}
local ret2={}
if Public.arrlen(table)==0 then return table end
for _,v in pairs(table) do
for _,v2 in pairs(ret) do
if ngx.re.find(v[0],v2,"jo") then
v[0]=ngx.re.gsub(v[0],v2,'baota',"jo")
end
end
v[0]=string.gsub(v[0],'%[','baota')
v[0]=string.gsub(v[0],'%(','baota')
v[0]=string.gsub(v[0],'%)','baota')
v[0]=string.gsub(v[0],'%+','baota')
v[0]=string.gsub(v[0],'%$','baota')
v[0]=string.gsub(v[0],'%?','baota')
end
return table
end
function upload.get_boundary()
local header = ngx.ctx.request_header["content-type"]
if not header then return nil end
if type(header) == "table" then
return Public.return_message(200,'content-type ERROR')
end
if header then
if ngx.re.find(header,[[multipart]],'ijo') then
if not ngx.re.match(header,'^multipart/form-data; boundary=',"jo") then
return Public.return_message(200,'content-type ERROR')
end
local multipart_data=ngx.re.match(header,'^multipart/form-data; boundary=.+',"jo")
if not multipart_data then return Public.return_message(200,"Btwaf Boundary Error") end
if ngx.re.match(multipart_data[0],'""',"jo") then
return Public.return_message(200,"Btwaf Boundary Double Quotation Mark Error")
end
local check_file=ngx.re.gmatch(multipart_data[0],[[=]],'ijo')
local ret={}
while true do
local m, err = check_file()
if m then
table.insert(ret,m)
else
break
end
end
if type(ret)~='table' then return false end
if(Public.arrlen(ret)>=2) then
return Public.return_message(200,"multipart/form-data ERROR")
end
return header
else
return false
end
end
end
function upload.ReadFileHelper4(str)
if type(str)~='string' then return str end
local res = string.gsub(str, "@", "")
return ngx.unescape_uri(res)
end
function upload.return_error2(rule,rule2)
ngx.ctx.is_type="http包非法"
ngx.ctx.error_rule = 'from-data 请求异常,拒绝访问,如有误报请点击误报'..' >> '..rule..' >> '..rule2
IpInfo.write_log('upload','from-data 请求异常,拒绝访问,如有误报请点击误报')
local check_html = [[
from-data请求error宝塔WAF提醒您,from-data 请求异常,拒绝访问,如有误报请点击误报
]]
ngx.header.content_type = "text/html;charset=utf8"
ngx.header.Cache_Control = "no-store"
ngx.say(check_html)
ngx.exit(200)
end
function upload.disable_upload_ext(ext)
local server_name =ngx.ctx.server_name
if not ext then return false end
ext=Public.get_fix(ext)
if type(ext)=='string' then
ext = string.lower(ext)
if ngx.re.match(ext,'\\.user\\.ini',"jo") or ngx.re.match(ext,'\\.htaccess',"jo") or ngx.re.match(ext,'\\.php',"jo") or ngx.re.match(ext,'\\.jsp',"jo") then
ngx.ctx.is_type='webshell防御'
IpInfo.lan_ip('upload','上传非法文件被系统拦截,并且被封锁IP')
return true
end
end
if not Site_config[server_name] then return false end
local disa=Site_config[server_name]['disable_upload_ext']
local ret={}
for _,k in ipairs(disa) do table.insert(ret,"\\."..k) end
if BTWAF_OBJS.request_check.is_ngx_match(ret,ext,'post') then
ngx.ctx.is_type='webshell防御'
IpInfo.lan_ip('upload','上传非法PHP文件被系统拦截,并且被封锁IP2'..' >> '..ext)
return true
end
end
function upload.return_error(int_age)
ngx.ctx.is_type='http包非法'
IpInfo.lan_ip('upload','http包非法,并且被封锁IP,如果自定义了from-data可能会导致误报。如果大量出现当前问题。请在全局设置->恶意文件上传防御->From-data协议 关闭此功能'..int_age)
end
function upload.disable_upload_ext2(ext)
local server_name =ngx.ctx.server_name
if not ext then return false end
if type(ext)~='table' then return false end
for i,k in pairs(ext) do
for i2,k2 in pairs(k) do
local check_file=ngx.re.gmatch(k2,[[filename=]],'ijo')
local ret={}
while true do
local m, err = check_file()
if m then
table.insert(ret,m)
else
break
end
end
if Public.arrlen(ret)>1 then
upload.return_error(1)
end
if not ngx.re.match(k2,[[filename=""]],'ijo') and not ngx.re.match(k2,[[filename=".+"]],'ijo') then
upload.return_error(2)
else
k2 = string.lower(k2)
if Site_config[server_name] ==nil then return false end
local disa=Site_config[server_name]['disable_upload_ext']
local ret_disa={}
for _,k in ipairs(disa) do table.insert(ret_disa,"\\."..k) end
if BTWAF_OBJS.request_check.is_ngx_match(ret_disa,k2,'post') then
ngx.ctx.is_type='恶意上传'
IpInfo.lan_ip('upload','上传非法PHP文件被系统拦截,并且被封锁IP3'..' >> '..k2)
return true
end
end
end
end
end
function upload.from_data(data,data2,data3)
if Public.arrlen(data) ==0 then return false end
local count=0
for k,v in pairs(data) do
if ngx.re.match(v[0],'filename=',"jo") then
if not ngx.re.match(v[0],'Content-Disposition: form-data; name="[^"]+"; filename=""\r*$','ijo') then
if not ngx.re.match(v[0],'Content-Disposition: form-data; name="[^"]+"; filename="[^"]+"\r*$','ijo') then
ngx.ctx.is_type='恶意上传'
upload.return_error2(v[0],'4.5')
end
end
count=count+1
upload.disable_upload_ext(v[0])
end
if Config['from_data'] then
if not ngx.re.match(v[0],'filename=',"jo") and not ngx.re.match(v[0],'Content-Disposition: form-data; name="[^"]+"\r*$','ijo') then
ngx.ctx.is_type='http包非法'
if not ngx.re.match(v[0],[[Content-Disposition: form-data; name=""]],'ijo') then
upload.return_error2(v[0],'5')
end
end
end
end
local len_count=Public.arrlen(data2)+Public.arrlen(data3)
if count ~=len_count then
ngx.ctx.is_type='http包非法'
upload.return_error2('','6')
end
end
function upload.disable_upload_ext3(ext,check)
local server_name =ngx.ctx.server_name
if not ext then return false end
if type(ext)~='table' then return false end
for i2,k2 in pairs(ext) do
local check_file=ngx.re.gmatch(k2,[[(\W)filename=]],'ijo')
local ret={}
while true do
local m, err = check_file()
if m then
table.insert(ret,m)
else
break
end
end
if Public.arrlen(ret)>5 then
upload.return_error(6)
end
if check==1 then
if Public.arrlen(ret)==0 then
if not k2 then return false end
if ngx.re.match(k2,[[Content-Disposition: form-data; name=".+\\"\r]],"jo") then
upload.return_error2('','0.1')
end
local kkkkk=ngx.re.match(k2,[[Content-Disposition:.{200}]],'ijo')
if not kkkkk then
if not ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\r]],'ijom') or ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\r;name=]],'ijo') or ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\r;\s*\r*\n*n\s*\r*\n*a\s*\r*\n*m\s*\r*\n*e\s*\r*\n*=]],'ijo') or ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\s*;]],'ijo') then
k2=string.gsub(k2,'\r','')
if ngx.re.match(k2,[[filename=]],'ijo') then
ngx.ctx.is_type='恶意上传'
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP1')
end
if not ngx.re.match(k2,[[Content-Disposition: form-data; name=""]],'ijo') and not ngx.re.match(k2,'^Content-Disposition: form-data; name=".+"','ijo') then
return upload.return_error2('','1')
end
end
else
k2=kkkkk[0]
if not ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\r]],'ijom') or ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\r;name=]],'ijo') or ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\r;\s*\r*\n*n\s*\r*\n*a\s*\r*\n*m\s*\r*\n*e\s*\r*\n*=]],'ijo') or ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"\r\s*;]],'ijo') then
k2=string.gsub(k2,'\r','')
if ngx.re.match(k2,[[filename=]],'ijo') then
ngx.ctx.is_type='恶意上传'
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP2')
end
return upload.return_error2('','2')
end
end
if k2 then
k2=string.gsub(k2,'\r','')
if ngx.re.match(k2,[[filename=]],'ijo') then
ngx.ctx.is_type='恶意上传'
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP3')
end
end
if ngx.re.match(k2,[[Content-Disposition: form-data; name="(.+)"\r]],'ijos') then
local tttt=ngx.re.match(k2,[[Content-Disposition: form-data; name="(.+)"\r\s]],'ijos')
if tttt==nil then return false end
if #tttt[0] >200 then return false end
if tttt[1] ==nil then return false end
tttt[1]=string.gsub(tttt[1],'\n','')
tttt[1]=string.gsub(tttt[1],'\t','')
tttt[1]=string.gsub(tttt[1],'\r','')
if ngx.re.match(tttt[1],'name=','ijo') then return upload.return_error2(tttt[1],tttt[1]) end
end
if ngx.re.match(k2,[[\r\r(.+)\r\r]],'ijos') then
local tttt=ngx.re.match(k2,[[\r\r(.+)\r\r]],'ijos')
if tttt==nil then return false end
if #tttt[0] >200 then return false end
if tttt[1] ==nil then return false end
tttt[1]=string.gsub(tttt[1],'\n','')
tttt[1]=string.gsub(tttt[1],'\t','')
tttt[1]=string.gsub(tttt[1],'\r','')
if ngx.re.match(tttt[1],'name=','ijo') then return upload.return_error2(tttt[1],tttt[1]) end
end
else
if not k2 then return false end
k2=string.gsub(k2,'\r','')
local k3=""
local kkkkk=ngx.re.match(k2,[[Content-Disposition:.{500}]],'ijo')
if not kkkkk then
k3=ngx.re.match(k2,[[Content-Disposition:.+Content-Type:]],'ijo')
ngx.ctx.is_type='恶意上传'
if not k3 then return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP4') end
if not ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"; filename=""Content-Type:]],'ijo') and not ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"; filename=".+"Content-Type:]],'ijo') then
ngx.ctx.is_type='恶意上传'
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP5')
end
else
k3=ngx.re.match(kkkkk[0],[[Content-Disposition:.+Content-Type:]],'ijo')
if not k3 then return false end
if not ngx.re.match(k3[0],[[Content-Disposition: form-data; name=".+"; filename=""Content-Type:]],'ijo') and not ngx.re.match(k3[0],[[Content-Disposition: form-data; name=".+"; filename=".+"Content-Type:]],'ijo') then
ngx.ctx.is_type='恶意上传'
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP7')
end
end
if Site_config[server_name] ==nil then return false end
local disa=Site_config[server_name]['disable_upload_ext']
local ret_disa={}
for _,k in ipairs(disa) do table.insert(ret_disa,"\\."..k) end
if BTWAF_OBJS.request_check.is_ngx_match(ret_disa,k3,'post') then
ngx.ctx.is_type='恶意上传'
IpInfo.lan_ip('upload','上传非法PHP文件被系统拦截,并且被封锁IP4')
end
if #k3[0] >500 then
local ret10={}
local tmp10 = ngx.re.gmatch(k3[0],'form-data',"jo")
while true do local m, err = tmp10() if m then table.insert(ret10,m) else break end end
if tonumber(Public.arrlen(ret10)) >1 then return false end
if ngx.re.match(k3[0],'--$') then return false end
return Public.return_message(200,'error1->The upload file name is too long')
end
local tmp8 = ngx.re.gmatch(k3[0],'\"',"jo")
local tmp9 = ngx.re.gmatch(k3[0],'=',"jo")
local tmp10 = ngx.re.gmatch(k3[0],';',"jo")
local ret8={}
local ret9={}
local ret10={}
while true do local m, err = tmp8() if m then table.insert(ret8,m) else break end end
while true do local m, err = tmp9() if m then table.insert(ret9,m) else break end end
while true do local m, err = tmp10() if m then table.insert(ret10,m) else break end end
if tonumber(Public.arrlen(ret9))~=2 and tonumber(Public.arrlen(ret8))~=4 and tonumber(Public.arrlen(ret10))~=2 then
upload.return_error2('','10')
end
end
else
if Public.arrlen(ret)==0 then
return false
else
local kkkkk=ngx.re.match(k2,[[Content-Disposition:.{500}]],'ijo')
local k3=""
if not kkkkk then
k3=ngx.re.match(k2,[[Content-Disposition:.+Content-Type:]],'ijo')
if not k3 then return upload.return_error(7) end
if ngx.re.match(k2,[[Content-Disposition: form-data; name=".+\\"]]) then
upload.return_error2('','10.33')
end
if not ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"; filename=""Content-Type:]],'ijo') and not ngx.re.match(k2,[[Content-Disposition: form-data; name=".+"; filename=".+"Content-Type:]],'ijo') then
ngx.ctx.is_type='恶意上传'
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP5')
end
else
if ngx.re.match(kkkkk[0],[[Content-Disposition: form-data; name=".+\\"]],"jo") then
upload.return_error2('','10.33')
end
k3=ngx.re.match(kkkkk[0],[[Content-Disposition:.+Content-Type:]],"jo")
if not k3 then
return false
end
if not ngx.re.match(k3[0],[[Content-Disposition: form-data; name=".+"; filename=""Content-Type:]],'ijo') and not ngx.re.match(k3[0],[[Content-Disposition: form-data; name=".+"; filename=".+"Content-Type:]],'ijo') then
ngx.ctx.is_type='恶意上传'
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP7')
end
end
k3=k3[0]
if not ngx.re.match(k3,[[filename=""Content-Type]],'ijo') and not ngx.re.match(k3,[[filename=".+"Content-Type]],'ijo') then
upload.return_error(8)
else
local check_filename=ngx.re.match(k3,[[filename="(.+)"Content-Type]],'ijo')
if check_filename then
if check_filename[1] then
if ngx.re.match(check_filename[1],'name=','ijo') then return upload.return_error(9) end
if ngx.re.match(check_filename[1],'php','ijo') then return upload.return_error(10) end
if ngx.re.match(check_filename[1],'jsp','ijo') then return upload.return_error(11) end
end
end
if #k3 >=500 then
ngx.ctx.is_type='文件名过长'
IpInfo.bt_ip_filterwrite_log('upload','上传的文件名太长了,被系统拦截')
return Public.return_message(200,'The uploaded file name is too long')
end
k3 = string.lower(k3)
if Site_config[server_name] ==nil then return false end
local disa=Site_config[server_name]['disable_upload_ext']
if BTWAF_OBJS.request_check.is_ngx_match(disa,k3,'post') then
ngx.ctx.is_type='恶意上传'
IpInfo.lan_ip('upload','上传非法PHP文件被系统拦截,并且被封锁IP1'..' >> '..k3)
return true
end
end
end
end
end
end
function upload.data_in_php(data)
return false
end
function upload.post_data()
-- if not config['post']['open'] or not is_site_config('post') then return false end
if not Config['file_upload'] or not Config['file_upload']['open'] then return false end
if ngx.ctx.method ~= "POST" then return false end
local content_length=tonumber(ngx.ctx.request_header['content-length'])
if not content_length then return false end
if content_length >108246867 then return false end
local boundary = upload.get_boundary()
if boundary then
ngx.req.read_body()
local data = ngx.req.get_body_data()
if not data then
data=ngx.req.get_body_file()
if data==nil then return false end
data=Public.read_file_body(data)
end
if not data then return false end
local data233=string.gsub(data,'\r','')
local tmp4 = ngx.re.gmatch(data,[[Content-Disposition.+]],'ijo')
local tmp5 = ngx.re.gmatch(data,[[Content-Disposition: form-data; name=".+"; filename=".+"\r\nContent-Type:]],'ijo')
local tmp6 = ngx.re.gmatch(data,[[Content-Disposition: form-data; name=".+"; filename=""\r\nContent-Type:]],'ijo')
local ret3={}
while true do local m, err = tmp4() if m then table.insert(ret3,m) else break end end
local ret5={}
while true do local m, err = tmp5() if m then table.insert(ret5,m) else break end end
local ret6={}
while true do local m, err = tmp6() if m then table.insert(ret6,m) else break end end
upload.from_data(ret3,ret5,ret6)
local tmp2 = ngx.re.gmatch(data,[[Content-Disposition.+filename=.+]],'ijo')
local tmp3 = ngx.re.gmatch(data,[[Content-Disposition.+\s*f\r*\n*o\r*\n*r\r*\n*m\r*\n*-\r*\n*d\r*\n*a\r*\n*t\r*\n*a\r*\n*\s*;\r*\n*\s*n\r*\n*a\r*\n*m\r*\n*e=\r*\n*.+;\s*f\n*\s*\r*i\n*\s*\r*l\n*\s*\r*e\n*\s*\r*n\n*\s*\r*a\n*\s*\r*m\n*\s*\r*e\n*\s*\r*=.+\n*\s*\r*]],'ijo')
local ret={}
while true do local m, err = tmp2() if m then table.insert(ret,m) else break end end
local ret2={}
while true do local m, err = tmp3() if m then table.insert(ret2,m) else break end end
upload.disable_upload_ext2(ret2)
if Public.arrlen(ret)==0 and Public.arrlen(ret2)>0 then
upload.return_error(3)
end
ret=upload.gusb_string(ret)
for k,v in pairs(ret) do
upload.disable_upload_ext(v)
end
local tmp2=ngx.re.match(data,[[Content-Type:[^\+]{100}]],'ijo')
if tmp2 and tmp2[0] then
upload.data_in_php(tmp2[0])
end
local av=ngx.re.match(boundary,"=.+","jo")
if not av then
IpInfo.write_log('upload','content_type_null')
Public.return_html(Config['post']['status'],BTWAF_RULES.post_html)
end
local header_data=ngx.re.gsub(av[0],'=','')
if #header_data>200 then
upload.return_error(5)
end
data=string.gsub(data,'\n','')
data=string.gsub(data,'\t','')
local tmp_pyload2 = ngx.re.match(data,'Content-Disposition:.+\r--','ijo')
if tmp_pyload2==nil then return false end
local tmpe_data2=Public.split2(tmp_pyload2[0],header_data)
if Public.arrlen(tmpe_data2)>0 then
if Config['from_data'] then
upload.disable_upload_ext3(tmpe_data2,1)
end
end
data=string.gsub(data,'\r','')
local tmp_pyload = ngx.re.match(data,'Content-Disposition:.+Content-Type:','ijo')
if tmp_pyload==nil then return false end
local tmpe_data=Public.split2(tmp_pyload[0],header_data)
if Public.arrlen(tmpe_data)>0 then
if Config['from_data'] then
upload.disable_upload_ext3(tmpe_data,2)
end
end
end
return false
end
function upload.return_post_data2()
if ngx.ctx.method ~= "POST" then return false end
local content_length=tonumber(ngx.ctx.request_header['content-length'])
if not content_length then return false end
local boundary = upload.get_boundary()
if boundary then
ngx.req.read_body()
local data = ngx.req.get_body_data()
if not data then
data=ngx.req.get_body_file()
if data==nil then return false end
data=Public.read_file_body(data)
end
if not data then return false end
local tmp2 = ngx.re.gmatch(data,[[Content-Disposition.+filename=]],'ijo')
local ret={}
while true do
local m, err = tmp2()
if m then
table.insert(ret,m)
else
break
end
end
ret=upload.gusb_string(ret)
if Public.arrlen(ret)>=1 then
for _,v in pairs(ret) do
if not ngx.re.match(v[0],'ContentbaotaDisposition: formbaotadata; name=".+"; filename=','ijo') and not ngx.re.match(v[0],'ContentbaotaDisposition: formbaotadata; name=”.+”; filename=','ijo') then
upload.return_error(12)
end
end
end
if Public.arrlen(ret)==1 then
return 1
else
return 2
end
end
return 3
end
function upload.ReadFileHelper(str)
if type(str)~='string' then return str end
local res = string.gsub(str, "\r", "")
res = string.gsub(res, "\n", "")
return res
end
function upload.table_key(tbl, key)
if tbl == nil then
return false
end
for k, v in pairs(tbl) do
if k == key then
return true
end
end
return false
end
function upload.chsize(char)
if not char then
print("not char")
return 0
elseif char > 240 then
return 4
elseif char > 225 then
return 3
elseif char > 192 then
return 2
else
return 1
end
end
function upload.utf8sub(str, startChar, numChars)
local startIndex = 1
while startChar > 1 do
local char = string.byte(str, startIndex)
startIndex = startIndex + upload.chsize(char)
startChar = startChar - 1
end
local currentIndex = startIndex
while numChars > 0 and currentIndex <= #str do
local char = string.byte(str, currentIndex)
currentIndex = currentIndex + upload.chsize(char)
numChars = numChars -1
end
return str:sub(startIndex, currentIndex - 1)
end
function upload.is_substitution(data)
data=ngx.re.sub(data,"\\+",'\\+')
return data
end
function upload.check_end(body, boundary)
if body == nil then return false end
if boundary == nil then return false end
if #body < #boundary then return false end
-- 检查body最后两位是否为\r\n
local lastTwo = string.sub(body, #body-1, #body)
local targetBoundary = boundary
-- 如果是\r\n,则将boundary加上\r\n
if lastTwo == "\r\n" then
targetBoundary = boundary .. "\r\n"
end
-- 确保处理后的targetBoundary长度不超过body
if #body < #targetBoundary then
return false
end
-- 计算新的起始位置并比较
local startIndex = #body - #targetBoundary + 1
local trailing = string.sub(body, startIndex)
return trailing == targetBoundary
end
function upload.post_data_chekc()
if not Config['file_upload'] or not Config['file_upload']['open'] then return false end
local content_length=tonumber(ngx.ctx.request_header['content-length'])
if not content_length then return false end
if content_length >108246867 then return false end
if ngx.ctx.method =="POST" then
local return_post_data=upload.return_post_data2()
if not return_post_data then return false end
if return_post_data==3 then return false end
ngx.req.read_body()
local request_args2=ngx.req.get_body_data()
if not request_args2 then
request_args2=ngx.req.get_body_file()
if request_args2==nil then return false end
request_args2=Public.read_file_body(request_args2)
end
if not request_args2 then return false end
if not ngx.ctx.request_header['content-type'] then return false end
if type(ngx.ctx.request_header['content-type']) ~= "string" then
if type(ngx.ctx.request_header['content-type']) ~= "string" then
upload.return_error(13)
end
end
local p, err = multipart.new(request_args2, ngx.var.http_content_type)
if not p then
return false
end
if not upload.check_end(p['body'],p['boundary2']..'--') then
ngx.ctx.is_type="http包未结尾"
ngx.var.waf2monitor_blocked=" from-data error 包结尾异常"
IpInfo.write_log('upload','from-data error 包结尾异常或结尾异常')
return Public.return_message(200,"btwaf is from-data error")
end
local site_count=0
local array = {}
while true do
local part_body, name, mime, filename,is_filename,header_data = p:parse_part()
if header_data then
local header_data_check=ngx.re.gmatch(header_data,[[Content-Disposition: form-data]],'ijo')
local ret={}
while true do
local m, err = header_data_check()
if m then
table.insert(ret,m)
else
break
end
end
if Public.arrlen(ret)>1 then
ngx.ctx.is_type="http包未结尾"
ngx.var.waf2monitor_blocked=" from-data error 包结尾异常"
IpInfo.write_log('upload','from-data error2 包结尾异常或结尾异常')
return Public.return_message(200,"btwaf is from-data error2")
end
end
if not is_filename then
break
end
site_count=site_count+1
if is_filename then
local filename_data=ngx.re.match(is_filename,'filename.+','ijo')
if filename_data then
ngx.ctx.is_type='webshell防御'
--if ngx.re.match(filename_data[0],'php','ijo') then return IpInfo.lan_ip('upload','上传非法PHP文件被系统拦截,并且被封锁IP13') end
--if ngx.re.match(filename_data[0],'\\.jsp','ijo') then return IpInfo.lan_ip('upload','上传非法PHP文件被系统拦截,并且被封锁IP14') end
local fix=Public.get_fix(filename_data[0])
-- 找到第一个点的位置
if ngx.re.match(fix, "\\.php", "ijo") then
return IpInfo.lan_ip("upload", "上传非法PHP文件被系统拦截 PHP")
end
if ngx.re.match(fix, "\\.jsp", "ijo") then
return IpInfo.lan_ip("upload", "上传非法jsp文件被系统拦截")
end
if ngx.re.match(fix, "\\.aspx", "ijo") then
return IpInfo.lan_ip("upload", "上传非法aspx文件被系统拦截")
end
if ngx.re.match(fix, "\\.asp", "ijo") then
return IpInfo.lan_ip("upload", "上传非法asp文件被系统拦截")
end
if ngx.re.match(fix, "\\.ashx", "ijo") then
return IpInfo.lan_ip("upload", "上传非法ashx文件被系统拦截")
end
if Config['from_data'] then
if not ngx.re.match(is_filename,'^Content-Disposition: form-data; name=".+"; filename=".+"Content-Type:','ijo') and not ngx.re.match(is_filename,'^Content-Disposition: form-data; name=".+"; filename=""Content-Type:','ijo') then
ngx.ctx.is_type='恶意上传'
ngx.var.waf2monitor_blocked="恶意上传文件"
if not ngx.re.match(is_filename,'^Content-Disposition: form-data; name="filename"$',"ijo") and not ngx.re.match(is_filename,'^Content-Disposition: form-data; name=".+"$',"ijo") then
return upload.return_error(20)
end
end
end
end
if(#is_filename)>1000 then
ngx.var.waf2monitor_blocked="恶意上传"
ngx.ctx.is_type="文件名过长"
IpInfo.lan_ip('upload','非法上传文件名长度超过1000被系统拦截,并封锁IP15')
end
end
if filename ~=nil then
ngx.ctx.is_type='webshell防御'
local fix=Public.get_fix(filename)
-- 找到第一个点的位置
if ngx.re.match(fix, "\\.php", "ijo") then
return IpInfo.lan_ip("upload", "上传非法PHP文件被系统拦截 PHP")
end
if ngx.re.match(fix, "\\.jsp", "ijo") then
return IpInfo.lan_ip("upload", "上传非法jsp文件被系统拦截")
end
if ngx.re.match(fix, "\\.aspx", "ijo") then
return IpInfo.lan_ip("upload", "上传非法aspx文件被系统拦截")
end
if ngx.re.match(fix, "\\.asp", "ijo") then
return IpInfo.lan_ip("upload", "上传非法asp文件被系统拦截")
end
if ngx.re.match(fix, "\\.ashx", "ijo") then
return IpInfo.lan_ip("upload", "上传非法ashx文件被系统拦截")
end
if ngx.re.match(fix, "\\.phar", "ijo") then
return IpInfo.lan_ip("upload", "上传非法phar文件被系统拦截")
end
if ngx.re.match(fix, "\\.soap", "ijo") then
return IpInfo.lan_ip("upload", "上传非法soap文件被系统拦截")
end
if ngx.re.match(filename,'name=','ijo') then return upload.return_error(15) end
if (#filename)>=1000 then
ngx.var.waf2monitor_blocked="恶意上传文件"
IpInfo.lan_ip('upload','非法上传文件名长度超过1000被系统拦截,并封锁IP15')
end
end
if name ==nil then
if part_body then
if #part_body>30 then
array[upload.utf8sub(part_body,1,30)]=part_body
else
array[part_body]=part_body
end
end
else
if #name >300 then
upload.return_error(16)
end
if filename ==nil then
if upload.table_key(array,name) then
for i=1, 1000 do
if not upload.table_key(array,name..'_'..i) then
if #name>30 then
array[upload.utf8sub(name,1,30)..'_'..i]=part_body
else
array[name..'_'..i]=part_body
end
break
end
end
else
if #name >30 then
array[upload.utf8sub(name,1,30)]=part_body
else
array[name]=part_body
end
end
if type(part_body)=='string' then
if (#part_body) >=BTWAF_RULES.body_size then
ngx.ctx.is_type="参数过长"
IpInfo.write_log('sql',name..' 参数值长度超过80w已被系统拦截')
Public.return_html(Config['post']['status'],BTWAF_RULES.post_html)
return true
end
end
else
if type(part_body) =='string' and part_body ~=nil then
if ngx.re.find(part_body,[["php"]],'ijo') or ngx.re.find(part_body,[['php']],'ijo') or ngx.re.find(part_body,[[<\?]],'ijo') or ngx.re.find(part_body,[[phpinfo\(]],'ijo') or ngx.re.find(part_body,[[\$_SERVER]],'ijo') or ngx.re.find(part_body,[[<\?php]],'ijo') or ngx.re.find(part_body,[[fputs]],'ijo') or ngx.re.find(part_body,[[file_put_contents]],'ijo') or ngx.re.find(part_body,[[file_get_contents]],'ijo') or ngx.re.find(part_body,[[eval\(]],'ijo') or ngx.re.find(part_body,[[\$_POST]],'ijo') or ngx.re.find(part_body,[[\$_GET]],'ijo') or ngx.re.find(part_body,[[base64_decode\(]],'ijo') or ngx.re.find(part_body,[[\$_REQUEST]],'ijo') or ngx.re.find(part_body,[[assert\(]],'ijo') or ngx.re.find(part_body,[[copy\(]],'ijo') or ngx.re.find(part_body,[[create_function\(]],'ijo') or ngx.re.find(part_body,[[preg_replace\(]],'ijo') or ngx.re.find(part_body,[[preg_filter\(]],'ijo') or ngx.re.find(part_body,[[system\(]],'ijo') or ngx.re.find(part_body,[[header_register_callback\(]],'ijo') or ngx.re.find(part_body,[[curl_init\(]],'ijo') or ngx.re.find(part_body,[[curl_error\(]],'ijo') or ngx.re.find(part_body,[[fopen\(]],'ijo') or ngx.re.find(part_body,[[stream_context_create\(]],'ijo') or ngx.re.find(part_body,[[fsockopen\(]],'ijo') then
local php_version=7
if Site_config[ngx.ctx.server_name]['php']~=nil then
php_version=tonumber(Site_config[ngx.ctx.server_name]['php'])
end
if php_engine.php_detected(part_body,php_version)==1 then
ngx.var.waf2monitor_blocked="webshell防御"
ngx.ctx.is_type='webshell防御'
IpInfo.lan_ip('upload','webshell防御.拦截木马上传,并被封锁IP')
end
end
--JSP/ASP/ASPX
if ngx.re.match(part_body, [[<%]], "ijo") or ngx.re.match(part_body, [[%>]], "ijo") then
if bt_engine.check_jsp(part_body) then
ngx.ctx.is_type = "上传JSP木马文件"
IpInfo.lan_ip("upload", "webshell防御.拦截JSP木马上传,并被封锁IP")
end
if bt_engine.check_asp(part_body) then
ngx.ctx.is_type = "上传ASP木马文件"
IpInfo.lan_ip("upload", "webshell防御.拦截ASP木马上传,并被封锁IP")
end
end
end
end
end
end
if site_count==0 then
if Config['from_data'] then
return upload.return_error2('','4')
end
end
if Public.count_sieze(array)>=3000 then
ngx.ctx.is_type='POST参数'
ngx.ctx.error_rule = '参数太多POST传递的参数数量超过800,拒绝访问,如有误报请点击误报'
IpInfo.write_log('sql','参数太多POST传递的参数数量超过800,拒绝访问,如有误报请点击误报')
Public.return_html_data('网站防火墙','您的请求带有不合法参数,已被网站管理员设置拦截','网站防火墙提醒您multipart/from-data传递的参数数量超过800,拒绝访问','点击误报')
end
if array['_method'] and array['method'] and array['server[REQUEST_METHOD]'] then
ngx.ctx.is_type='ThinkPHP攻击'
ngx.var.waf2monitor_blocked="ThinkPHP攻击"
IpInfo.lan_ip('php','拦截ThinkPHP 5.x RCE 攻击')
end
if array['_method'] and array['method'] and array['server[]'] and array['get[]'] then
ngx.ctx.is_type='ThinkPHP攻击'
ngx.var.waf2monitor_blocked="ThinkPHP攻击"
IpInfo.lan_ip('php','拦截ThinkPHP 5.x RCE 攻击,并且被封锁IP')
end
if array['_method'] and ngx.re.match(array['_method'],'construct','ijo') then
ngx.ctx.is_type='ThinkPHP攻击'
ngx.var.waf2monitor_blocked="ThinkPHP攻击"
IpInfo.lan_ip('php','拦截ThinkPHP 5.x RCE 攻击,并且被封锁IP')
end
BTWAF_OBJS.request_check.args_urlencoded(Public.process_json_args(array))
for i,v in pairs(array) do
if ngx.re.match(i,'\\\\$','ijo') then
ngx.ctx.is_type='恶意上传'
ngx.var.waf2monitor_blocked="恶意上传"
return IpInfo.lan_ip('upload','非法上传请求已被系统拦截,并且被封锁IP11')
end
end
end
end
return upload