最新消息:Kglan博客,DDOS防护,CC防护,Syn防护,系统架构,高级网络安全,海外无限防护系统,特征码系统,自定义cc策略防护

ngx_lua_waf针对性改写

nginx admin 60浏览

ngx_lua_waf针对性改写

当初选择ngx_lua_waf作为自己的WAF,主要原因就是因为其可扩展性与性能上有一个很好的平衡。

LUA语言的灵活性与效率是很多WAF无可匹及的。

ngx_lua_waf自身是一个比较简单的,而且存在很多误报,漏报,绕过的现象,我整理如下,来改进自己的WAF。


1.debug函数

预备一个调试函数,方便以后调试。因为WAF运行在后台,所以看不到输出,最好以日志的形式写到文件中。


功能调试(信息)

local file = io.open(“/ tmp / debug.log”,“a”)

文件:写(信息。 “\ n”)

文件:关闭()

结束


2.waf可以用HPP进行绕过

作为作者一处笔误(我认为的),我提交到乌云了:HTTP://wooyun.org/bugs/wooyun-2010-0104525

等公开了,可以用里面的方法修改。


3.利用白名单绕过

wafconf / whiteurl中,白名单网址直接是/ 123 /

然后在函数whiteurl中


功能whiteurl()

如果WhiteCheck那么

如果wturlrules~ = nil那么

for _,成对规则(wturlrules)

如果ngxmatch(ngx.var.request_uri,规则,“ijom”)那么

返回true

结束

结束

结束

结束

返回false

结束


用的是ngx.var.request_uri和这个 “/ 123 /” 进行比较,只要URI中存在/ 123 /就作为白名单不进行检测,这样我们可以通过/waf.php?a=/123/&b=。 ./etc/passwd绕过防御规则。

所以,将/ 123 /改成^ / 123 /

这样只有以/ 123 /开头的URI才能进入白名单。


4.正则是米还是小号

WAF绕的多的人一定知道正则里“”代表什么意义。

正常情况下,匹配的是“不含换行”的所有字符所以有些WAF用这样的正则。:


工会。*选择


来拦截注入。我们就可以通过工会%0aselect,中间一个换行来绕过。

所以,现在一般的WAF都会用小号来修饰正则的.s的意思就是单一的,也就是单行模式。

说白了,加了小号修饰,则“”就会匹配换行了。

而我们的ngx_lua_waf中,所有的正则都用的米来修饰的,米的意思是多个,多行的意思,也就是默认的。不匹配换行。

比如对GET变量的拦截:


函数args()

for _,成对规则(argsrules)

local args = ngx.req.get_uri_args()

对于密钥,val成对(args)

如果键入(val)=='table'那么

如果val == false那么

data = table.concat(val,“”)

结束

其他

数据= VAL

结束

如果数据和类型(数据)〜=“布尔”和规则〜=“”和ngxmatch(unescape(数据),规则,“imjo”)然后

日志( 'GET',ngx.var.request_uri, “ – ”,规则)

say_html()

返回true

结束

结束

结束

返回false

结束


可见ngxmatch(UNESCAPE(数据),规则, “imjo”),用的是imjo来修饰我们用工会%0aselect就能绕过WAF:



5.误杀误杀!上传文件的误杀。

对HTTP协议了解的同学一定心里清楚,POST的类型是分两种的:应用/ X WWW的窗体-urlencoded和多部分/格式数据

前一种是默认POST数据的时候使用的,服务器获取了数据后会进行URL解码。后一种一般是上传的时候才会使用,服务器获取数据后不会进行URL解码,所以我们能直接上传二进制文件。

PHP在上传过程中,上传文件的表单会放进$ _FILES变量,其他POST表单会放进$ _ POST变量,和直接应用程序/ x-WWW窗体-urlencoded的效果一样。

这部分POST变量在LUA中需要特殊处理,原ngx_lua_waf的作者也考虑了,具体拦截代码可见waf.lua。

但作者处理的太草率,直接把整个数据包,一点一点丢进体函数里检测这样造成了两个问题:


①。数据包一部分一部分发过来,他就一部分一部分丢进body里检测。那么如果union,select two个连在一起的关键词正好从中间某位置分开,比如“unio”和“n select”,这两个包分别检测都是正常的。但实际发送到PHP里的时候是连在一起的,导致绕过WAF。

②。文件里的特殊字符也被拦截了,所谓的误杀。有时候我们要上传一些文件,文件里可能会有的HTML标签,或SQL语句,这里他将上传表单的内容也放入体内检测了,导致很多文件上传不了。


。我对上述问题做了修改与处理,不过代码太多我就不写在文章里了思路就是这样:

首先将完整的数据包获取下来,并用边界将他们分割成数组。遍历数组,只对进入POST变量的值进行拦截,不拦截FILE内容。但需要拦截FILE表单中的 “文件名= XXX” 的部分。


6.人性化提示信息

虽然我的WAF拦截的80%是攻击者,但也可能有正常访客。这时候我就需要告诉访客,你输入了哪些东西不合理被我拦截(误杀)了,你可以换个方式输入或通知我。

我在init.lua靠前的位置加入如下代码:


local fd = io.open(file403,“r”)

如果fd == nil那么

html = [[403 error !!]]

其他

html = fd:read(“* a”)

FD:关闭()

结束


file403是我自己写的403页面,读取之并将say_html函数改成这个:


功能say_html(原因)

如果重定向则

本地nowhtml = html

ngx.header.content_type =“text / html”

nowhtml = string.gsub(nowhtml,“{ip}”,ngx.var.remote_addr)

nowhtml = string.gsub(nowhtml,“{host}”,ngx.var.host)

nowhtml = string.gsub(nowhtml,“{reason}”,reason)

ngx.say(nowhtml)

ngx.exit(200)

结束

结束



将HTML里的{IP},{主},{}原因改成具体的信息即可在用户被拦截后发出提示:

如果需要优化SEO,我将ngx.exit(200)改成403,避免搜索引擎收录这个页面。但后来发现状态代码并没有改变。

研究了一会,发现如果在ngx.exit之前输出了内容,则这个退出里的参数403就会失效。需要在退出前,先用ngx.status = ngx.HTTP_FORBIDDEN,将状态设置成ngx.HTTP_FORBIDDEN,也就是403才可。


7.利用lua_ngx_waf防御盗链

以前防盗链都是用nginx的自己的模块进行配置,但有时候灵活性不高。

有了lua waf,就可以灵活地防御盗链了。

我大概写了个简陋的雏形,需要更精细化的配置,就得各位日后再慢慢修改了。


function check_referer()

local referer = ngx.var.valid_referers

local ua = string.lower(ngx.var.http_user_agent)

local exts = [[\。(gif | jpg | jpeg | png | bmp | js | css | swf)$]]

本地http =“http”

如果ngx.var.https ==“on”则http =“https”结束

local white_referer = {[0] = [[^]] ..http .. [[:// [^ /] *]] ..ngx.var.host .. [[[^ /] * /。*] ],[1] = [[^ https?:// [^ /] * google \ .com [^ /] * /。*]],[2] = [[^ https?:// [^ /] *百度\ .COM [^ /] * /。*]]}

local white_ua = {[0] =“googlebot”,[1] =“蜘蛛”}

如果referer~ = nil和ngxmatch(ngx.var.request_filename,exts,“ijos”)那么

对于white_referer中的rex

如果ngxmatch(referer,rex,“ijos”)然后返回true end

结束

对于rex in white_ua do

如果ngxmatch(ua,rex,“ijos”)然后返回true end

结束

ngx.exit(403)

结束

结束



尾声

通过这几日对ngx_lua_waf的研究,WAF这块的攻击与防御,我也初步接触到了。我也知道有时候我们研究者说绕过WAF,似乎总在指责WAF的开发者,某某没考虑到,某某可以绕过了。实际上做WAF也不容易,往往是因为要考虑到业务效率,兼容性等各种原因,写出来的代码才被绕过去。

安全有时候不得不为业务让道,有时候明知这么写是不安全的,但某些用户就需要这样的数据包,我们不能抛弃这部分用户,那么只能尽全力改变这些用户的习惯,写出兼容性更好的代码。

我希望的是,通过自己的研究,让更多人知道WAF都是怎么做出来的,会遇到哪些问题,有哪些绕过方法。

攻防,也不过就是那句老话:知己知彼,百战不殆。

转载请注明:Kglan » ngx_lua_waf针对性改写