使用Naxsi搭建WAF

NAXSI(Nginx Anti XSS & SQL Injection)是一个第三方的nginx模块。Naxsi管理员的职责是将合法行为的特定规则列入白名单。

编译nginx+naxsi

1
2
3
# ./auto/configure --add-module=./modules/naxsi-0.56/naxsi_src
# make
# make install

配置nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http {
include naxsi/naxsi_core.rules;
server {
location / {
SecRulesEnabled;
#LearningMode;
include naxsi/whitelist.conf;

DeniedUrl "/RequestDenied";
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
error_log logs/naxsi.log;
}
location = /RequestDenied {
return 403;
}
}
}

naxsi工作流程

Naxsi的行为类似于Drop by default的防火墙,唯一任务是为目标网站添加所需的Accept规则(whitelist)以使其正常工作,可通过分析nginx的错误日志手动添加白名单,或者(推荐)通过自动学习阶段自动生成有关网站行为的白名单规则。

Naxsi在学习模式下不会拒绝被拦截的请求,但被拦截的请求会被写入naxsi指定的日志文件中。因此在部署完成naxsi之后需要打开学习模式,再对网站进行完整测试,测试完成后可将naxsi拦截的正常请求日志导入到elasticsearch,再通过nxapi自动生成白名单。待白名单配置完成后需要关闭学习模式,则违反白名单规则的非法请求将自动被拦截。

安装ELK

创建索引

1
# curl -XPUT 'http://localhost:9200/nxapi/'

配置nxapi

由于nxapi为python程序,依赖elasticsearch,通过pip安装Python Elasticsearch 模块默认版本为6,但nxapi仅支持elasticsearch 1、2、5版本,为防止出现兼容性问题, 选择安装 elasticsearch5 模块

1
2
3
4
5
# cd /path/nxapi/
# pip install elasticsearch5
# sed -i 's/import elasticsearch/import elasticsearch5 as elasticsearch/' nxtool.py
# sed -i 's/elasticsearch/elasticsearch5/' nxapi/nxparse.py
# sed -i 's/elasticsearch/elasticsearch5/' nxapi/nxtypificator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# vi nxapi.json
{
"elastic": {
"host": "127.0.0.1:9200",
"use_ssl": false,
"index": "nxapi",
"number_of_shards": "4",
"number_of_replicas": "0",
"doctype": "events",
"default_ttl": "7200",
"max_size": "1000",
"version": "2"
},
"syslogd": {
"host": "0.0.0.0",
"port": "51400"
},
"global_filters": {
"whitelisted": "false"
},
"global_warning_rules": {
"rule_ip": ["<=", 10],
"global_rule_ip_ratio": ["<", 5]
},
"global_success_rules": {
"global_rule_ip_ratio": [">=", 10],
"rule_ip": [">=", 10]
},
"global_deny_rules": {
"global_rule_ip_ratio": ["<", 2]
},
"naxsi": {
"rules_path": "/usr/local/yealink/nginx/conf/naxsi/naxsi_core.rules",
"template_path" : [ "/usr/local/nxapi/tpl/"],
"geoipdb_path" : "/usr/local/nxapi/country2coords.txt"
},
"output": {
"colors": "true",
"verbosity": "5"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Usage: nxtool.py [options]

Options:
-h, --help show this help message and exit

Configuration options:
-c CFG_PATH, --config=CFG_PATH
Path to nxapi.json (config).
--colors Disable output colorz.

Input options (log acquisition):
--files=FILES_IN Path to log files to parse.
--fifo=FIFO_IN Path to a FIFO to be created & read from. [infinite]
--stdin Read from stdin.
--no-timeout Disable timeout on read operations (stdin/fifo).
--syslog Listen on tcp port for syslog logging.

Filtering options (for whitelist generation):
-s SERVER, --server=SERVER
FQDN to which we should restrict operations.
--filter=FILTER This option specify a filter for each type of filter,
filter are merge with existing templates/filters.
(--filter 'uri /foobar')

Tagging options (tag existing events in database):
-w WL_FILE, --whitelist-path=WL_FILE
A path to whitelist file, will find matching events in
DB.
-i IPS, --ip-path=IPS
A path to IP list file, will find matching events in
DB.
--tag Actually tag matching items in DB.

Whitelist Generation:
-f, --full-auto Attempt fully automatic whitelist generation process.
-t TEMPLATE, --template=TEMPLATE
Path to template to apply.
--slack Enables less strict mode.
--type Generate whitelists based on param type

Statistics Generation:
-x, --stats Generate statistics about current's db content.

Interactive Whitelists Generation:
-g, --interactive-generation
Use your favorite text editor for whitelist
generation.

查看导入ES的naxsi日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# nxtool.py -x
# size :1000
# Whitelist(ing) ratio :
# false 50.0% (total:581/1162)
# Top servers :
# 10.200.112.78 100.0% (total:581/581)
# Top URI(s) :
# static 23.06% (total:134/581)
# js 13.08% (total:76/581)
# yms 12.91% (total:75/581)
# passwd 11.7% (total:68/581)
# etc 10.84% (total:63/581)
# gemfile 8.61% (total:50/581)
# fileserver 8.26% (total:48/581)
# 1 5.68% (total:33/581)
# html 5.51% (total:32/581)
# php 4.82% (total:28/581)
# phpthumb.php 4.82% (total:28/581)
# Top Zone(s) :
# url 40.1% (total:233/581)
# args 33.91% (total:197/581)
# body 19.97% (total:116/581)
# headers 6.02% (total:35/581)
# Top Peer(s) :
# 10.86.4.4 82.96% (total:482/581)
# 10.200.112.21 11.02% (total:64/581)
# 10.86.4.10 5.16% (total:30/581)
# 10.200.110.119 0.86% (total:5/581)

生成 whitelist

1
# nxtool.py -s 10.200.112.78 --filter 'ip 10.86.4.10' -f --slack

--filter支持的参数包含server, uri, zone, var_name, ip, id, content, country, date,?server, ?uri, ?var_name, ?content。(?开头的参数为支持正则表达式)

若出现以下报错,则需要将text类型的 fields fielddata置为 true

Fielddata is disabled on text fields by default. Set fielddata=true on [id] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.

1
2
3
4
5
6
7
8
9
PUT /nxapi/_mapping/<text_field_name>?update_all_types
{
"properties": {
"<text_field_name>": {
"type": "text",
"fielddata": true
}
}
}

naxsi日志

NAXSI_FMT由以下字段组成:

  • ip:客户端的ip
  • server:请求的server
  • uri:请求的URI
  • learning:是否处于学习模式(0/1)
  • vers:Naxsi版本
  • total_processed:nginx worker处理的请求总数
  • total_blocked:被naxsi阻止的请求总数
  • zoneN:发生匹配的区域
  • idN:匹配的规则ID
  • var_nameN:匹配发生的变量名称
  • cscoreN:命名分数标记
  • scoreN:关联的命名分数值
    几个zone,id,var_name,cscore和score组可以出现在一行中。
1
2018/12/25 07:28:12 [error] 1536#0: *23078 NAXSI_FMT: ip=117.28.234.34&server=cloud-pressure.yealinkops.com&uri=/&learning=1&vers=0.56&total_processed=1&total_blocked=1&block=1&cscore0=$XSS&score0=48&zone0=HEADERS&id0=1315&var_name0=cookie, client: 117.28.234.34, server: cloud-pressure.yealinkops.com, request: "GET / HTTP/1.1", host: "cloud-pressure.yealinkops.com"

NAXSI_EXLOG

NAXSI_EXLOG是naxsilogs的补充。 它还包含匹配请求的实际内容。

需要在nginx配置的server{}中启用。
set $naxsi_extensive_log 1;

1
2018/12/25 08:09:01 [error] 6292#0: *23096 NAXSI_EXLOG: ip=117.28.234.34&server=cloud-pressure.yealinkops.com&uri=%2Fmeeting%2Fmeeting%2Fstatic%2Fcss%2Fapp.7043a8b74bcb93be14f7685967598f92.css&id=1315&zone=HEADERS&var_name=cookie&content=UM_distinctid%3D164ab24940a558-0989f1192f4877-444a022e-1fa400-164ab24940c439%3B%20JSESSIONID%3Ds%253A5iM7C8jbXREu-s8FCJbIhpMPaqEgMQEV.gQhJLU0jWitOu2yP0wt6rAJyjSzJpS6aaSOncQd1ooU, client: 117.28.234.34, server: cloud-pressure.yealinkops.com, request: "GET /meeting/meeting/static/css/app.7043a8b74bcb93be14f7685967598f92.css HTTP/1.1", host: "cloud-pressure.yealinkops.com", referrer: "https://cloud-pressure.yealinkops.com/"

坚持原创技术分享,您的支持将鼓励我继续创作!
0%