Hexo

Naxsi 配置白名单

2018-08-21

在Nginx下安装和配置完Naxsi之后,为了能够使网站能够区分非法行为和合法行为,需要管理员将合法行为列入白名单。管理员可以通过分析nginx的错误日志手动添加白名单规则,或者通过密集的自动学习工具(nxapi或nxtool),这些工具将自动生成有关网站行为的白名单规则。本文主要介绍白名单规则以及如何通过分析nginx错误日志手动添加白名单规则。

白名单规则配置

naxsi核心规则文件naxsi_core.rules需要在nginx配置文件nginx.conf下的http部分导入,而naxsi白名单规则文件naxsi_whitelists.rules一般在nginx配置文件nginx.conf下的location部分导入,可放置在CheckRules语句之前。

location部分对应的配置内容如下。

include naxsi_whitelists.rules;#导入白名单规则
SecRulesEnabled;
DeniedUrl "/RequestDenied";
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >=4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
error_log /path/to/foo.log;#配置Naxsi错误日志

为了区分Naxsi和Nginx的错误日志,可以为Naxsi设置相应的错误日志目录和文件名。在本文中,Naxsi对应的错误日志为foo.log。

白名单规则语法

如果服务器安装的是Wordpress或者ruTorrent或者dokuwiki或者drupal等,可以直接在naxsi-rules找到Naxsi官方制作的白名单。如果都没有找到适合的白名单,就只能自己去配置白名单了。

白名单规则的语法如下所示。然后介绍语法中的重要组成部分。

BasicRule wl:ID [negative] [mz:[$URL:target_url]|[match_zone]|[$ARGS_VAR:varname]|[$BODY_VARS:varname]|[$HEADERS_VAR:varname]|[NAME]]

Whitelisted ID (wl:…)

这部分指的是哪些拦截规则会进入白名单。以下举例进行说明。

wl:0 : 把所有拦截规则加入白名单
wl:42 : 把ID为42的拦截规则加入白名单
wl:42,41,43 : 把ID为42, 41 和 43的拦截规则加入白名单
wl:-42 : 把所有拦截规则加入白名单,除了ID为42的拦截规则

MatchZone (mz:…)

这部分指的是本条白名单的生效区域。区域有如下组成部分。

  • ARGS: GET的整个参数内容,如: foo=bar&in=%20
  • $ARGS_VAR: GET参数的参数名, 如 foo=bar&in=%20中的 foo和in。
  • $ARGS_VAR_X: 正则匹配的GET参数的参数名
  • HEADERS: 整个HTTP协议头内容
  • $HEADERS_VAR: HTTP协议头的参数名
  • $HEADERS_VAR_X: 正则匹配的HTTP协议头的参数名
  • BODY: POST的整个参数内容
  • $BODY_VAR: POST参数的参数名
  • $BODY_VAR_X: 正则匹配的POST参数的参数名
  • URL(整个链接?前的部分链接)
  • $URL:域名后的路径
  • $URL_X: 正则匹配的URL(整个链接?前的部分链接)
  • FILE_EXT: 文件名 (POST上传文件时上传的文件名)
  • RAW_BODY: HTTP请求的BODY部分的原始的未解析的内容

白名单规则示例

以下对静态的白名单规则进行举例说明。

  1. BasicRule wl:1000;

    已知拦截规则1000是过滤包含select|union|update|delete|insert|table|from|ascii|hex|unhex之类SQL关键字的规则。

    在本子规则中完全禁用拦截规则1000。因为没有指定区域,所以全部加入白名单。

  1. BasicRule wl:1000 “mz:$ARGS_VAR:foo”;

    在全部GET参数名为foo的值中禁用拦截规则1000 (即不用1000规则检查GET中参数名为foo中的值)。所以, http://127.0.0.1/?foo=select * from a 不会被过滤。

  2. BasicRule wl:1000 “mz:$ARGS_VAR:foo|$URL:/bar”;

    在URL为/bar的GET请求中参数名为foo的值中禁用拦截规则1000。所以, http://127.0.0.1/bar?foo=select * from a 不会被过滤。

  3. BasicRule wl:1000 “mz:$URL:/bar|ARGS”;

    在URL为/bar的GET请求中的参数禁用拦截规则1000。所以, http://127.0.0.1/bar?my=select * from a 不会被过滤。http://127.0.0.1/bar?from=weibo 也不会被过滤。

  4. BasicRule wl:1000 “mz:ARGS|NAME”;

    在全部GET请求中对所有参数名(只是名,不包含参数值)中禁用拦截规则1000。所以, http://127.0.0.1?from=weibo 不会被过滤。但是, http://127.0.0.1?foo=select 会被过滤(因为select属于参数值,不在白名单范围内)。

  5. BasicRule wl:1000 “mz:$URL:/bar|ARGS|NAME”;

    在URL为/bar的全部GET请求中对所有参数名(只是名,不包含参数值)中禁用拦截规则1000。所以, http://127.0.0.1/bar?from=weibo 不会被过滤。但是, http://127.0.0.1/bar?foo=select 会被过滤(因为select属于参数值,不在白名单范围内)。

  6. BasicRule wl:0 “mz:$URL_X:^/upload/(.).(.)$|URL”;

    在全部请求中对符合^/upload/(.).(.)$正则规则的URL禁用全部拦截规则。所以, http://127.0.0.1/upload/select.db 不会被过滤 (原本会触发1000拦截规则)。

以下对含正则表达式的白名单规则进行举例说明。

  1. BasicRule wl:1000 “mz:$ARGS_VAR_X:meh”;

    在全部GET参数名含有meh的值中禁用拦截规则1000 (即不用1000规则检查GET中参数名含有meh中的值)。所以, http://127.0.0.1/?smehe=select * from a 不会被过滤。

  2. BasicRule wl:1000 “mz:$ARGS_VAR_X:^meh”;

    在全部GET参数名以meh开始的值中禁用拦截规则1000 (即不用1000规则检查GET中参数名以meh开始的值)。所以, http://127.0.0.1/?mehe=select * from a 不会被过滤。

  3. BasicRule wl:1000 “mz:$ARGS_VAR_X:^meh_[0-9]+$”

    在全部GET参数名格式为“meh_数字”的值中禁用拦截规则1000 (即不用1000规则检查GET中参数名格式为“meh_数字”的值)。所以, http://127.0.0.1/?meh_12=select * from a 不会被过滤。

  4. BasicRule wl:1000 “mz:$URL_X:^/foo|ARGS”;

    在URL以/foo开始的GET请求中的参数禁用拦截规则1000。所以, http://127.0.0.1/foo1?my=select * from a 不会被过滤。http://127.0.0.1/foo2?from=weibo 也不会被过滤。

  5. BasicRule wl:1000 “mz:$URL_X:^/foo|$ARGS_VAR_X:^[0-9]”;

    在URL以/foo开始的GET请求中的以数字开始命名的参数禁用拦截规则1000。所以, http://127.0.0.1/foo1?2my=select * from a 不会被过滤。http://127.0.0.1/foo2?1from=weibo 也不会被过滤。

以下对RAW_BODY的白名单规则进行举例说明。以RAW_BODY为目标的白名单规则的编写方式与任何其他BODY规则相同。

  1. BasicRule wl:4241 “mz:$URL:/|BODY”;

    已知拦截规则4241是即便在学习模式下也要过滤RAW_BODT中包含字符串RANDOMTHINGS的规则。
    在本子规则中,在URL为/的BODY中的内容禁用拦截规则4241,意味着该目录下的任意BODY内容都不会被过滤。

以下对FILE_EXT的白名单规则进行举例说明。

  1. BasicRule wl:1337 “mz:$URL:/index.html|FILE_EXT”;

    在本子规则中,在URL为/index.html的文件上传部分禁用拦截规则1337,意味着可在该目录下上传任意文件。

以下对JSON的白名单规则进行举例说明。

  1. BasicRule wl:1302 “mz:$BODY_VAR:lol”;

    JSON可被当作BODY, 以变量的形式表示文本内容。在本子规则中,对POST的参数lol禁用拦截规则1302,即以下JSON内容可以被通过。

    {

    "lol" : "foo<bar"

    }

手动编写白名单规则

以下为访问http://yourwebsiteaddress/?foo=select * from a的错误日志记录。

2018/08/19 13:35:16 [error] 1#0: *187 NAXSI_FMT: ip=*.*.*.*&server=yourwebsiteaddress&uri=/&learning=0&vers=0.55.3&total_processed=116&total_blocked=1&block=1&cscore0=$SQL&score0=4&cscore1=$XSS&score1=8&zone0=ARGS&id0=1000&var_name0=foo, client: 10.30.169.105, server: bkjy.xmu.edu.cn, request: "GET /?a=select%20*%20from%20a HTTP/1.1", host: "bkjy.xmu.edu.cn"

从zone0=ARGS可看出被过滤的区域是ARGS,从id0=1000可看出拦截规则的id是1000,从var_name0=foo可看出被过滤的变量为foo。因此可以编写如下白名单规则。

BasicRule wl:1000 "mz:$ARGS_VAR:foo";

参考资料

1.Naxsi Wiki
2.NGINX的WAF模块-Naxsi 配置白名单
3.whitelists-bnf
4.matchzones-bnf
5.whitelists-examples