ngx.req.get_uri_args, ngx.req.get_post_args,ngx.req.get_headers 默认解析前100个内容
FAQ: ngx.req.get_uri_args, ngx.req.get_post_args,ngx.req.get_headers 默认解析前100个内容,后面的内容将不会获得到
比如使用nginx_lua做waf很多代码都只是使用默认值,如
local r_headers = ngx.req.get_headers()
local r_uri_args = ngx.req.get_uri_args()
然后开始检测,是否包含危险请求,但是根据nginx_lua官方说明
ngx.req.get_uri_args()
ngx.req.get_post_args()
ngx.req.get_headers()
三个api,有最大长度限制,默认是100个,api官方文档
https://github.com/openresty/lua-nginx-module#ngxreqget_post_args
因此,当请求参数超过取得最大值限制,其后的参数将不会被lua读取,进而不会进行规则检测,比如当检测规则为information_schema字符串,请求,是没有办法检测到攻击:
/test.php?&a0=0&a1=1&a2=2&a3=3&a4=4&a5=5&a6=6&a7=7&a8=8&a9=9&a10=10&a11=11&a12=12&a13=13&a14=14&a15=15&a16=16&a17=17&a18=18&a19=19&a20=20&a21=21&a22=22&a23=23&a24=24&a25=25&a26=26&a27=27&a28=28&a29=29&a30=30&a31=31&a32=32&a33=33&a34=34&a35=35&a36=36&a37=37&a38=38&a39=39&a40=40&a41=41&a42=42&a43=43&a44=44&a45=45&a46=46&a47=47&a48=48&a49=49&a50=50&a51=51&a52=52&a53=53&a54=54&a55=55&a56=56&a57=57&a58=58&a59=59&a60=60&a61=61&a62=62&a63=63&a64=64&a65=65&a66=66&a67=67&a68=68&a69=69&a70=70&a71=71&a72=72&a73=73&a74=74&a75=75&a76=76&a77=77&a78=78&a79=79&a80=80&a81=81&a82=82&a83=83&a84=84&a85=85&a86=86&a87=87&a88=88&a89=89&a90=90&a91=91&a92=92&a93=93&a94=94&a95=95&a96=96&a97=97&a98=98&a=%23information_schemas
据不完全统计,使用nginx_lua的开源模块,都存在该问题,比如lua-resty-waf,官网如下:
https://github.com/p0pr0ck5/lua-resty-waf
已经反馈作者,参考:
https://github.com/p0pr0ck5/lua-resty-waf/issues/280
解决方案:
如ngx.req.get_uri_args API官方说明:
https://www.openresty.com.cn/nginx-lua-module-zh-wiki.html#ngxreqget_uri_args
原文如下:
请注意,为防止拒绝服务式攻击 (denial of service attacks),默认最多解析前 100 个请求参数 (包括同名的),更多的参数将直接忽略。
可选的 max_args 函数参数可以用来修改这个限制:
local args = ngx.req.get_uri_args(10)
这个参数可以被设置为 0 以移除此限制,此时将解析所有接收到的请求参数:
local args = ngx.req.get_uri_args(0)
强烈不推荐移除 max_args 限制。
该api设置默认值,主要是为了防止被DoS攻击。如果想违背作者的意图,可以移除对max_args的限制。
使用:ngx.req.get_uri_args(0) 获得参数,其它两个类似API也是如此。
但这真的可能如作者缩写面临被DoS的风险??怎么解决
通过对超长参数限制?
比如业务正常请求参数个数保持在100以内,偏偏给我们发200个参数,直接就阻断好了。试想,如果一个URI真的接收100个key,这个页面真的是该下线了。