http请求数据进行解码
针对用户请求/提交的数据进行解码操作,以免存在绕过waf的请求,导致恶意payload被后端执行。
在观察模式下解码操作可以配合response分析一起来使用,用以判断请求-响应是否一个完整的恶意攻击,如果是一个完整的编码绕过攻击,形成攻击知识库。
例如某些商业化成熟的waf产品,在针对xss攻击payload识别时,在用户提交一个字符量很大的请求,利用词法分析只提取某些某一段字符进行分析,这些字符是可以被解析器执行的。从而大大节省无用的匹配操作减少性能损耗,真正的把攻击或疑似攻击的payload提取出来进行检查。
如下代码仅提供解码的思路,在waf实际工作中,针对编码识别是一个很大的工程。
针对http get请求的url参数(query string)解码过滤。也可以针对http post上传内容进行解码过滤。
--base64解码
base64_decode = function(value)
if not value then return end
--判断是否是base64编码
--if ngx_re_match(value,"^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$") ~= nil then
local t_val = ngx_decode_base64(tostring(value))
if t_val then
ngx.log(ngx.ERR,'Decode successful, before decoded value is '..value..' after decode is '..t_val)
return t_val
else
return value
end
return value
end,
--base64编码
base64_encode = function(value)
if not value then return end
local t_val = ngx_encode_base64(value)
return t_val
end,
--css解码
css_decode = function(value)
if not value then return end
if not value then return end
local len = #value
local buf = decode_buf_helper(value, len)
local n = decode_lib.css_decode(buf, len)
return (ffi_str(buf, n))
end,
--命令行处理
cmd_line = function(value)
if not value then return end
local str = tostring(value)
str = ngx_re_gsub(str, [=[[\\'"^]]=], '', 'oij')
str = ngx_re_gsub(str, [=[\s+/]=], '/', 'oij')
str = ngx_re_gsub(str, [=[\s+[(]]=], '(', 'oij')
str = ngx_re_gsub(str, [=[[,;]]=], ' ', 'oij')
str = ngx_re_gsub(str, [=[\s+]=], ' ', 'oij')
return string_lower(str)
end,
--空格处理
compress_whitespace = function(value)
if not value then return end
return ngx_re_gsub(value, [=[\s+]=], ' ', 'oij')
end,
--十六进制解码
hex_decode = function(value)
if not value then return end
return util.hex_decode(value)
end,
--十六进制编码
hex_encode = function(value)
if not value then return end
return util.hex_encode(value)
end,
--html解码
html_decode = function(value)
if not value then return end
local str = hdec.decode(value)
return str
end,
--js解码
js_decode = function(value)
if not value then return end
local len = #value
local buf = decode_buf_helper(value, len)
local n = decode_lib.js_decode(buf, len)
return (ffi_str(buf, n))
end,
--string长度计算
length = function(value)
if not value then return end
return string_len(tostring(value))
end,
--大小写
lowercase = function(value)
if not value then return end
return string_lower(tostring(value))
end,
--MD5转换
md5 = function(value)
if not value then return end
return ngx_md5_bin(value)
end,
--路径字符串处理
normalise_path = function(value)
if not value then return end
while (ngx.re.match(value, [=[[^/][^/]*/\.\./|/\./|/{2,}]=], 'oij')) do
value = ngx_re_gsub(value, [=[[^/][^/]*/\.\./|/\./|/{2,}]=], '/', 'oij')
end
return value
end,
--windows路径字符串处理
normalise_path_win = function(value)
if not value then return end
value = string_gsub(value, [[\]], [[/]])
return _M.lookup['normalise_path'](value)
end,
--移除注释字符
remove_comments = function(value)
if not value then return end
return ngx_re_gsub(value, [=[\/\*(\*(?!\/)|[^\*])*\*\/]=], '', 'oij')
end,
remove_comments_char = function(value)
if not value then return end
return ngx_re_gsub(value, [=[\/\*|\*\/|--|#]=], '', 'oij')
end,
--移除\0空字符
remove_nulls = function(value)
if not value then return end
return ngx_re_gsub(value, [[\0]], '', 'oij')
end,
--移除空格
remove_whitespace = function(value)
if not value then return end
return ngx_re_gsub(value, [=[\s+]=], '', 'oij')
end,
--字符替换操作
replace_comments = function(value)
if not value then return end
return ngx_re_gsub(value, [=[\/\*(\*(?!\/)|[^\*])*\*\/]=], ' ', 'oij')
end,
replace_nulls = function(value)
if not value then return end
return ngx_re_gsub(value, [[\0]], ' ', 'oij')
end,
sha1 = function(value)
if not value then return end
return ngx_sha1_bin(value)
end,
--sql-hex解码
sql_hex_decode = function(value)
if not value then return end
if string_find(value, '0x', 1, true) then
value = string_sub(value, 3)
return util.hex_decode(value)
else
return value
end
end,
--字符串左右剪切
trim = function(value)
if not value then return end
return ngx_re_gsub(value, [=[^\s*|\s+$]=], '')
end,
trim_left = function(value)
if not value then return end
return ngx_re_sub(value, [=[^\s+]=], '')
end,
trim_right = function(value)
if not value then return end
return ngx_re_sub(value, [=[\s+$]=], '')
end,
--uri解码
uri_decode = function(value)
if not value then return end
return ngx_unescape_uri(value)
end,