freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

软WAF的另一种思路:基于Openresty+Naxsi的WAF实现
2018-05-10 14:00:25

* 本文作者: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架构

waf.png

0×03 WAF管理后台

由于WAF使用了两个独立的nginx模块,所以需要两套完全不同的配置文件。naxsi模块的防护规则配置需要以文件的形式下发到nginx节点,Lua代码也需要以文件的形式下发到nginx节点。为实现文件的下发和同步,我们将配置文件放到WAF的管理端,由WAF的nginx节点定期通过http访问管理端下载配置文件。

其中naxsi的配置文件建议和lua的代码分开存放。

image.png

配置文件的管理,为了防止修改配置文件出错而造成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为站点的防护规则配置,主要有防护规则的配置文件和站点防护规则配置文件

TIM图片20180507121134.png0

**_active-mode.rules 是站点的防护模式配置

image3.png

**.rules是站点的规则配置文件,因加载了naxsi的全局配置规则,一般waf会出现大量的误拦的情况,所以该规则文件主要还是配置站点的白名单规则。

image4.png

因为每个节点是根据nginx.conf配置所配置的内容选择的配置文件,所以每个nginx节点将会同步所有的WAF配置文件。

Lua模块采用的redis+django的方式实现了配置的管理,可以通过web管理后台直接修改配置。

waf节点状态展示

image5.png

url访问频率限制

image6.png

站点防护功能配置

image7.png

实时拦截情况展示

image8.png

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.rulesweb_apps.rulesscanner.rulesapp_server.rules等防护规则。

rules.conf的配置可以参考如下:

image9.png

在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

image10.png

http request kibana dashboa

image11.png

0×07 总结

通过Lua+naxsi的整合,可满足基本的web安全防护需求,WAF功能目前还比较简陋,WAF还在不断完善中,如有不足的地方欢迎各位大佬指出。

* 本文作者:erwinlic,本文属FreeBuf原创奖励计划,未经许可禁止转载

# Openresty # naxsi
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者