Nginx1.14.0+ModSecurity实现简单的WAF
1.安装依赖环境
$ yum -y install gcc-c++ flex bison yajl yajl-devel curl-devel curl GeoIP-devel doxygen zlib-devel libtool git autoconf automake libxml2-devel zlib-devel libgo-devel openssl-devel
2.安装Nginx
$ wget http://nginx.org/download/nginx-1.14.0.tar.gz $ tar xvf nginx-1.14.0.tar.gz -C /usr/local/src/ $ cd /usr/local/src/nginx-1.14.0 $ ./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_flv_module \ --with-http_stub_status_module \ --with-http_gzip_static_module \ --with-pcre \ --with-file-aio \ --with-http_secure_link_module \ --with-compat \ --with-http_addition_module \ --with-http_auth_request_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_gzip_static_module \ --with-http_mp4_module \ --with-http_random_index_module \ --with-http_realip_module \ --with-http_secure_link_module $ make && make install
3.编写Nginx启动脚本
$ vim /usr/lib/systemd/system/nginx.service [Unit] Description=nginx - high performance web server After=network-online.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/usr/local/nginx/logs/nginx.pid ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID [Install] WantedBy=multi-user.target
4.修改环境PATH
$ vim /etc/profile.d/nginx.sh PATH=/usr/local/nginx/sbin:$PATH $ source /etc/profile
二、下载并编译libmodsecurity
$ cd /usr/local/src $ git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity $ cd ModSecurity/ $ git submodule init $ git submodule update $ ./build.sh $ ./configure # 此步骤时间较长 $ make && make install
在编译的时候出现如下情况是正常情况
三、配置ModSecurity和Nginx的连接
1.下载ModSecurity和Nginx的连接器
$ cd /usr/local/src/ $ git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git $ nginx -V $ cd /usr/local/src/nginx-1.14.0/ $ ./configure ...(-V获取的configure arguments) --add-dynamic-module=/usr/local/src/ModSecurity-nginx $ make modules # 如果之前的是二进制的nginx的话,直接cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/ $ make install # 会显示如下信息,如果之前没有modules目录,也会生成 cp objs/ngx_http_modsecurity_module.so '/usr/local/nginx/modules/ngx_http_modsecurity_module.so'
2.加载Nginx ModSecurity
$ vim /usr/local/nginx/conf/nginx.conf 在顶级区间内加上 load_module /usr/local/nginx/modules/ngx_http_modsecurity_module.so; $ nginx -t
3.下载默认的配置文件
$ cd /usr/local/src $ wget https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended $ mv modsecurity.conf-recommended /usr/local/nginx/conf/modsecurity.conf $ vim /usr/local/nginx/conf/modsecurity.conf SecRuleEngine On
1.SecRuleEngine:是否接受来自ModSecurity-CRS目录下的所有规则的安全规则引擎。因此,我们可以根据需求设置不同的规则。要设置不同的规则有以下几种。SecRuleEngine On:将在服务器上激活ModSecurity防火墙,它会检测并阻止该服务器上的任何恶意攻击。SecRuleEngine Detection Only:如果设置这个规则它只会检测到所有的攻击,并根据攻击产生错误,但它不会在服务器上阻止任何东西。SecRuleEngine Off:这将在服务器上上停用ModSecurity的防火墙。
2.SecRequestBodyAccess:它会告诉ModSecurity是否会检查请求,它起着非常重要的作用。它只有两个参数ON或OFF。
3.SecResponseBodyAccess:如果此参数设置为ON,然后ModeSecurity可以分析服务器响应,并做适当处理。它也有只有两个参数ON和Off,我们可以根据求要进行设置。
4.SecDataDir:定义ModSecurity的工作目录,该目录将作为ModSecurity的临时目录使用。
4.配置核心规则
$ git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git $ cp -R owasp-modsecurity-crs/rules /usr/local/nginx/conf/ $ cp owasp-modsecurity-crs/crs-setup.conf.example /usr/local/nginx/conf/crs-setup.conf $ vim /usr/local/nginx/conf/modsecurity.conf include crs-setup.conf include rules/*.conf
5.修改nginx的配置文件
$ vim /usr/local/nginx/conf/nginx.conf # 放在server下的话,就是全局,如果只要某一个的话,可以放在location中 modsecurity on; modsecurity_rules_file /usr/local/nginx/conf/modsecurity.conf; $ nginx -t nginx: [emerg] "modsecurity_rules_file" directive Rules error. File: /usr/local/nginx/conf/modsecurity.conf. Line: 237. Column: 17. Failed to locate the unicode map file from: unicode.mapping Looking at: 'unicode.mapping', 'unicode.mapping', '/usr/local/nginx/conf/unicode.mapping', '/usr/local/nginx/conf/unicode.mapping'. in /usr/local/nginx/conf/nginx.conf:73 方法一: 如果有如上错误的话,可以修改 /usr/local/nginx/conf/modsecurity.conf 搜索mapping,将SecUnicodeMapFile unicode.mapping 20127 注释掉 方法二: 将unicode.mapping复制到modsecurity.conf同一目录下。 $ cp /usr/local/src/ModSecurity/unicode.mapping /usr/local/nginx/conf/ $ nginx -t $ systemctl restart nginx
四.测试
1.正常访问 192.168.1.93
2.带上正常的参数访问 192.168.1.93/?id=1
3.在正常的参数的基础上其他参数
加上AND 1=1
此时Nginx就会返回403 Forbidden的信息,说明Modsecurity成功拦截了此请求。
访问192.168.1.93/?search=<scritp>alert('xss');</script>
(模拟简单的XSS跨站攻击)
访问被拒绝,查看日志cat /var/log/modsec_audit.log
---CN4pqdMj---A-- [10/Jan/2019:14:02:56 +0800] 154710017669.078147 192.168.1.235 2139 192.168.1.235 80 ---CN4pqdMj---B-- GET /?id=1%20AND%201=1 HTTP/1.1 Host: 192.168.1.93 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7 ---CN4pqdMj---D-- ---CN4pqdMj---E-- <html>\x0d\x0a<head><title>403 Forbidden</title></head>\x0d\x0a<body bgcolor="white">\x0d\x0a<center><h1>403 Forbidden</h1></center>\x0d\x0a<hr><center>nginx</center>\x0d\x0a</body>\x0d\x0a</html>\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a ---CN4pqdMj---F-- HTTP/1.1 403 Server: nginx Date: Thu, 10 Jan 2019 06:02:56 GMT Content-Length: 564 Content-Type: text/html Connection: keep-alive ---CN4pqdMj---H-- ModSecurity: Warning. Matched "Operator `Rx' with parameter `^[\d.:]+$' against variable `REQUEST_HEADERS:Host' (Value: `192.168.1.93' ) [file "/usr/local/nginx/conf/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "768"] [id "920350"] [rev ""] [msg "Host header is a numeric IP address"] [data "192.168.1.93"] [severity "4"] [ver "OWASP_CRS/3.1.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [hostname "192.168.1.235"] [uri "/"] [unique_id "154710017669.078147"] [ref "o0,12v38,12"] ModSecurity: Warning. detected SQLi using libinjection. [file "/usr/local/nginx/conf/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "43"] [id "942100"] [rev ""] [msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: 1&1 found within ARGS:id: 1 AND 1=1"] [severity "2"] [ver "OWASP_CRS/3.1.0"] [maturity "0"] [accuracy "0"] [hostname "192.168.1.235"] [uri "/"] [unique_id "154710017669.078147"] [ref "v9,9"] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `8' ) [file "/usr/local/nginx/conf/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "80"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 8)"] [data ""] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "192.168.1.235"] [uri "/"] [unique_id "154710017669.078147"] [ref ""] ModSecurity: Warning. Matched "Operator `Ge' with parameter `5' against variable `TX:INBOUND_ANOMALY_SCORE' (Value: `8' ) [file "/usr/local/nginx/conf/rules/RESPONSE-980-CORRELATION.conf"] [line "76"] [id "980130"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 8 - SQLI=5,XSS=0,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0): SQL Injection Attack Detected via libinjection; individual paranoia level scores: 8, 0, 0, 0"] [data ""] [severity "0"] [ver ""] [maturity "0"] [accuracy "0"] [tag "event-correlation"] [hostname "192.168.1.235"] [uri "/"] [unique_id "154710017669.078147"] [ref ""] ---CN4pqdMj---I-- ---CN4pqdMj---J-- ---CN4pqdMj---Z--