* 本文作者:erwinlic,本文属FreeBuf原创奖励计划,未经许可禁止转载
0×00 WAF概要
目前软WAF的开发,大部分都采用Nginx+Lua基于openresty的方式,安全防护策略如果是基于lua正则匹配http请求内容的话,在加载了大量的防护规则后,nginx的性能会大大降低。
本文采用了lua+naxsi整合的方式,使用lua来实现如cc攻击的防护、IP访问频率限制等相对复杂的安全防护策略,使用Naxsi来防护相对简单的http请求内容策略规则,有效的扬长避短,大大提升nginx 防护性能。
0×01 WAF功能
Naxsi在本WAF中主要实现基于http请求内容的防护策略规则,用于防护一些常见的漏洞,如:
SQL注入攻击 XSS攻击 目录遍历漏洞 命令注入攻击 虚拟补丁 扫描器攻击等
Lua在本waf中主要负责实现相对复杂的安全防护策略,如cc攻击防护、全局IP访问频率限制、特定url访问频率限制、ip黑白名单防护、url白名单防护、http请求转发等功能。
WAF管理后台可实现WAF节点的统一管理,本WAF可以基于云WAF模式部署或者直接嵌入到应用现有的nginx的方式部署。
0×02 WAF架构
0×03 WAF管理后台
由于WAF使用了两个独立的nginx模块,所以需要两套完全不同的配置文件。naxsi模块的防护规则配置需要以文件的形式下发到nginx节点,Lua代码也需要以文件的形式下发到nginx节点。为实现文件的下发和同步,我们将配置文件放到WAF的管理端,由WAF的nginx节点定期通过http访问管理端下载配置文件。
其中naxsi的配置文件建议和lua的代码分开存放。
配置文件的管理,为了防止修改配置文件出错而造成nginx运行异常,我们通过python脚本结合nginx检查配置文件是是否正确,并且做到了配置文件有更新才去服务端拉取文件并且reload nginx,避免了频繁的reload nginx节点。
def get_rules_file(rulesdir,rulesfile):
for filename in os.listdir(rulesdir):
if filename not in ['files.txt', 'files.md5', 'get_naxsi-rules.py', 'install_naxsi_rules.py']:
CalcMD5(rulesdir,filename,rulesfile)
def CalcMD5(path,filename,rulesfile):
filepath = path + filename
with open(filepath,'rb') as f:
md5obj = hashlib.md5()
md5obj.update(f.read())
hash = md5obj.hexdigest()
rulesfile.write(filename + ';,' + hash + '\n')
print filename + ';,' + hash
def calc_files_md5(filedir,fimename):
files_md5 = open(fimename,"w")
filepath = filedir + 'files.txt'
with open(filepath,'rb') as f:
md5obj = hashlib.md5()
md5obj.update(f.read())
hash = md5obj.hexdigest()
files_md5.write(hash)
f.close()
def check_rules():
check = commands.getstatusoutput("/usr/local/nginx/sbin/nginx -t")
if check[0] == 0:
pattern = re.compile(r'test is successful')
match = pattern.search(check[1])
if match:
msg = "rules update successful"
print msg
get_rules_file(rulesdir,naxsi_rulesfile)
naxsi_rulesfile.close()
calc_files_md5(rulesdir,naxsi_md5_file)
get_rules_file(lua_waf_dir, lua_waf_file)
lua_waf_file.close()
calc_files_md5(lua_waf_dir,lua_wafi_md5_file)
commands.getstatusoutput("/usr/local/nginx/sbin/nginx -s reload")
else:
msg = "rules update fales"
print msg
else:
msg = check[1]
print check[0]
print msg
return msg
为了后续的自动化生成配置文件,naxsi的个性化配置文件要由三个文件组成
**_rules.conf为站点的防护规则配置,主要有防护规则的配置文件和站点防护规则配置文件
0
**_active-mode.rules 是站点的防护模式配置
**.rules是站点的规则配置文件,因加载了naxsi的全局配置规则,一般waf会出现大量的误拦的情况,所以该规则文件主要还是配置站点的白名单规则。
因为每个节点是根据nginx.conf配置所配置的内容选择的配置文件,所以每个nginx节点将会同步所有的WAF配置文件。
Lua模块采用的redis+django的方式实现了配置的管理,可以通过web管理后台直接修改配置。
waf节点状态展示
url访问频率限制
站点防护功能配置
实时拦截情况展示
0×04 Naxsi配置
如要加载Naxsi,需要在nginx的http段include naxsi全局的配置文件rules.conf。在这里,我们将naxsi_core.rules 跟doxi-rules放到一个rules.conf文件内,
doxi-rules是naxsi rules的一个发布版本,是naxsi_core.rules的一个补充,doxi-rules主要包括了web_server.rules、 web_apps.rules、scanner.rules、 app_server.rules等防护规则。
rules.conf的配置可以参考如下:
在nginx的每个server段加入 set $naxsi_extensive_log 1; 开启naxsi的扩展日志记录功能,可以记录下具体触发naxsi拦截规则的请求内容,方便后续分析拦截的是攻击请求还是误拦了正常的业务请求。
在nginx的每个server的location 段加入include /etc/nginx/naxsi-rules/**_rules.conf; 具体的规则配置文件。通过该配置文件,可以区分出不同的应用,方便WAF naxsi 防护策略的统一管理。
在每个server加入 拦截后跳转的location配置
location /RequestDenied {
rewrite ^ http://security.*****.com/block?type=1&msec=$msec&url=$scheme://$host$request_uri redirect;
}
0×05 Lua 配置
为了方便配置在nginx中加载waf配置,我们将Lua的配置统一写到一个配置文件内,只需要incloud 到nginx的http段内即可。
配置文件的内容如下
lua_package_path "/etc/nginx/lua_waf/?.lua;/usr/local/lib/lua/?.lua;;";
init_by_lua '
waf = require("waf");
--根据应用名称修改app_name
app_name = "cc";
';
init_worker_by_lua '
cron = require("cron");
';
access_by_lua_file /etc/nginx/lua_waf/access.lua;
log_by_lua_file /etc/nginx/lua_waf/sendlog.lua;
0×06 WAF日志管理
Naxsi kibana dashboa
http request kibana dashboa
0×07 总结
通过Lua+naxsi的整合,可满足基本的web安全防护需求,WAF功能目前还比较简陋,WAF还在不断完善中,如有不足的地方欢迎各位大佬指出。
* 本文作者:erwinlic,本文属FreeBuf原创奖励计划,未经许可禁止转载