之前的文章中介绍了nginx的一种waf,是添加modsecurity模块来作为nginx的waf,功能很强大,nginx官方plus版本中其实也是用modsecurity作为waf的,但是modsecurity对于普通用户来说配置相对复杂,特别是它的规则,所以,今天推荐一个开源、高性能、低规则维护的waf——Naxsi


Naxsi用于防护XSS和SQL注入以及RFI、文件上传、CSRF,这些都是web安全中最常见的攻击方式,它是一个第三方的nginx模块,依赖于libpcre,与任何nginx版本都兼容


为了验证它的功能,我先通过docker,起一个dvwa,用没有安装Naxsi的nginx反代这个dvwa,先用sqlmap跑一下。然后在nginx上安装Naxsi,之后同样用工具跑一下,看下两次结果对比,这个就是整体的一个思路,废话不多说,开搞!





未安装前测试




先docker search一下web-dvwa,就用这个stars 110的

Nginx的WAF——Naxsi_java


直接启动容器,映射端口

Nginx的WAF——Naxsi_java_02


看下日志,是否启动正常了

Nginx的WAF——Naxsi_java_03

看来是Apache+MariaDB,正常启动了,通过nginx反向代理一下

Nginx的WAF——Naxsi_java_04

重启nginx,访问

Nginx的WAF——Naxsi_java_05

通过默认用户名密码登录之后,创建数据库

Nginx的WAF——Naxsi_java_06

创建完成后,会跳转到登录页面,同样默认用户名密码登录之后,可以看到创建成功的dvwa

Nginx的WAF——Naxsi_java_07


ok,dvwa安装完之后,通过sqlmap测一下注入

Nginx的WAF——Naxsi_java_08

直接跑一下数据库,跑出结果如下:

Nginx的WAF——Naxsi_java_09





安装Naxsi



开始安装Naxsi,首先从git上下载naxsi源码及配置文件

Nginx的WAF——Naxsi_java_10

目录结构如下

Nginx的WAF——Naxsi_java_11

如果你没有nginx源码包,下载对应版本的nginx源码包,完成后进入nginx源码包,编译安装naxsi为动态扩展

Nginx的WAF——Naxsi_java_12

然后通过make modules,安装模块为ngx_http_naxsi_module.so,保存在objs目录,复制到nginx的modules目录,同时将naxsi的主配置文件复制到/etc/nginx下

Nginx的WAF——Naxsi_java_13

在nginx配置文件中,加载naxsi模块和核心规则

Nginx的WAF——Naxsi_java_14

ok,添加完成模块,检测配置是否正常,如果遇到以下错误,说明这个第三方模块的编译中包含的签名和nginx的不一致

Nginx的WAF——Naxsi_java_15

通过nginx -V获取当前配置的configure参数,复制所有参数,后面添加增加模块的编译参数,重新编译就可以了

Nginx的WAF——Naxsi_java_16





安装后测试




上面添加模块后,在需要启用规则的location添加规则Nginx的WAF——Naxsi_java_17

然后重载nginx,再拿sqlmap跑一次注入看下结果

Nginx的WAF——Naxsi_java_18被拦截,查看日志

Nginx的WAF——Naxsi_java_19





Naxsi规则



上面简单的加了基本的规则进行测试,下面对Naxsi规则进一步说明


首先是naxsi支持的几个变量,它们通常是在server块进行配置

  • naxsi_flag_learning    是否开启学习

  • naxsi_flag_post_action    是否post_action

  • naxsi_flag_enable    是否启用naxsi

  • naxsi_extensive_log    是否强制记录变量匹配规则

  • naxsi_flag_libinjection_sql    是否启用libinjection的sql规则

  • naxsi_flag_libinjection_xss    是否启用libinjection的xss规则


由于naxsi是在nginx的REWRITE阶段运行的(关于nginx的几个阶段,将在下篇文章介绍),这几个变量需要在调用前设置,否则无效


上面几个变量设置后,会覆盖后面的设置,比如上面例子中设置SecRulesEnabled,是开启naxsi的,当设置naxsi_flag_enable时,会覆盖该项


当然这些变量都可以通过nginx的if或lua脚本进行动态判断设置


接着是常用的配置指令,都是在location块进行配置

  • DeniedUrl    拒绝之后重定向的url

  • LearningMode    学习模式

  • SecRulesEnabled    启用规则

  • SecRulesDisabled    禁用规则

  • CheckRule    检查规则

  • BasicRule    基本规则(通常声明白名单)

  • MainRule    主要规则

  • LibInjectionXss    在http请求的所有部分启用libinjection的xss检测指令

  • LibInjectionSql    在http请求的所有部分启用libinjection的sql检测指令


这里需要注意学习模式,开启学习模式后,通常不会进行拦截id大于1000的规则,默认情况下小于1000的规则是被注释掉的


DeniedUrl是指配置一个naxsi拒绝访问之后返回的错误页面,比如40x或50x错误页面,也可以是自定义的一个页面


关于白名单,很多时候会用到,通常白名单可以设置在location,也可以设置在MainRule中,通常的语法如下:

BasicRule wl:1013 "mz:$ARGS_VAR:term|$URL:/search";

语法规则是wl表示白名单,冒号后面的id表示加入白名单的规则,常见

  • wl:0 : Whitelist all rules    所有规则加入白名单

  • wl:42 : Whitelist rule #42   42号规则加入白名单

  • wl:42,41,43 : Whitelist rules 4241 and 43    多个规则加入白名单

  • wl:-42 : Whitelist all user rules (>= 1000), excepting     rule 42    除42号规则,其他都加入白名单

上面的语法中还有mz部分,这部分是指不是整个id都加入白名单,而是将id中匹配到后面变量和url的部分加入白名单


mz全名是Match Zones,主要有4个区域,分别是URL、ARGS、HEADERS、BODY,分别解释如下:

  • URL:就是我们常说的url,?之前的部分

  • ARGS:GET请求参数

  • HEADERS:HTTP headers部分

  • BODY:POST请求参数


最后说下CheckRule,CheckRule用来指示naxsi根据与请求相关联的特定得分,采取相应的操作,比如LOG、DROP、BLOCK、ALLOW,这里说的分数通常是由一个或几个规则确定的


例如上面的例子中,CheckRule "$SQL >= 8" BLOCK; 这个分数是在主规则中创建的

Nginx的WAF——Naxsi_java_20

所以可以根据你要禁用的匹配规则,利用分数来进行CheckRule设定


除了以上这些基本的规则外,naxsi还可以通过nxapi和nxtool工具组合,并通过es数据库生产白名单,通过导入es数据库正常的请求日志,来制作白名单


另外还可以集成fail2ban等工具,更多的高级使用方式可以通过wiki查看https://github.com/nbs-system/naxsi/wiki