一、ModSecurity和OWASP

ModSecurity是一个免费、开源的Apache模块,可以充当Web应用防火墙(WAF)。ModSecurity从3.0开始支持nginx,配合nginx的灵活和高效,可以打造成生产级的WAF,是保护和审核web安全的利器。

ModSecurity的主要功能在于,提供可靠的保护,远离各种网上威胁。它不是将安全重心偏离应用程序,而是增添了全局级别的功能。想对它进行配置,只需为客户机与服务器之间通信的每一个部分用条件和操作来指定规则,这些部分包括请求头、请求主体、响应头和响应主体。因而,ModSecurity可以预防针对Web服务器、PHP、Perl和ASP等解释器以及Web应用程序发动的攻击。

OWASP是一个安全社区,开发和维护着一套免费的应用程序保护规则,这就是所谓OWASP的ModSecurity的核心规则集(即CRS)。我们可以通过ModSecurity手工创建安全过滤器、定义攻击并实现主动的安全输入验证。

二、nginx中添加ModSecurity模块

2.1 查看当前nginx编译选项

如果设备已经安装了nginx,先记住当前的nginx编译选项。使用nginx -V命令可以查看编译选项:

[art@centos7 ~]$ nginx -V
nginx version: Tomcat/1.0.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/usr/local/nginx-1.12.2 --with-http_stub_status_module --with-http_ssl_module

最后一行就是nginx安装时的编译选项,先记住。

2.2 下载ModSecurity代码

拉取ModSecurity主代码,当前版本是3.x。ModSecurity在3.0以后已经不止是一个模块了,主代码库编译出来的是一个公共库,可以被第三方代码直接引用,现如今的ModSecurity-nginx就是通过这个lib库来完成的。

因此,整个modsecurity功能目前一共涉及到三个东西:

  1. ModSecurity的lib库
  2. ModSecurity的nginx模块
  3. owasp规则

克隆ModSecurity代码:

git clone https://github.com/SpiderLabs/ModSecurity.git

克隆ModSecurity-nginx代码:

git clone https://github.com/SpiderLabs/ModSecurity-nginx.git

克隆owasp-modsecurity-crs代码:

git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git

三个代码都克隆完成后,应该存在以下三个目录:

maqian@Inspiron:/usr/src/software$
total 20
drwxrwxr-x  5 root   root   4096 6月   1 19:48 ./
drwxr-xr-x  9 root   root   4096 6月   1 19:41 ../
drwxrwxr-x 13 maqian maqian 4096 6月   1 19:44 ModSecurity/
drwxrwxr-x  5 maqian maqian 4096 6月   1 19:47 ModSecurity-nginx/
drwxrwxr-x  7 maqian maqian 4096 6月   1 19:48 owasp-modsecurity-crs/

进入到ModSecurity目录,初始化子模块,这一步相当重要,否则后面会出错

cd ModSecurity
git submodule init
git submodule update

2.3 集成ModSecurity到nginx

2.3.1 下载依赖项

依赖项注意区分系统环境,除此之外后面的流程都不再依赖系统环境。

CentOS环境:

sudo yum install autoconf automake libtool gcc gcc-c++ make
sudo yum install yum install prce pcre-devel openssl openssl-devel

Ubuntu系统:

sudo apt-get install autoconf automake libtool gcc g++ make
sudo apt-get install openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev

2.3.2 编译ModSecurity

进入ModSecurity目录:

./build.sh
./configure
make && sudo make install

因为后面的modsecurity-nginxnginx编译都依赖modsecurity的lib库,为了方便起见,直接把编译后的库文件放到默认目录,不手动指定安装目录。

2.3.3 nginx编译安装

如果没有安装nginx,先下载好nginx代码,nginx的编译安装参考:CentOS源码编译安装NGINX。如果已经安装了nginx,记录nginx当前的编译选项,参考步骤2.1

nginx是否安装不重要,不同的是如果没有安装就要先下载源代码,如果安装了就记录下编译选项。

假设安装时候的编译选项为:

--user=www --group=www --prefix=/usr/local/nginx-1.12.2 \
    --with-http_stub_status_module --with-http_ssl_module

进入nginx目录:

./configure --user=www --group=www \
    --prefix=/usr/local/nginx-1.12.2 \
    --with-http_stub_status_module --with-http_ssl_module \
    --add-module=../ModSecurity-nginx/
make && sudo make install

安装好后nginx的配置参考上面的文档即可。

2.3.4 配置OWASP Core Rule Set

owasp-modsecurity-crs开始已经下载到本地,首先拷贝一份到nginx配置目录,假设安装到/etc/nginx/owasp目录下:

cp owasp-modsecurity-crs /etc/nginx/owasp/ -rf
mv /etc/nginx/owasp/crs-setup.conf.example /etc/nginx/owasp/crs-setup.conf

配置ModSecurity:

cp ModSecurity/modsecurity.conf-recommended /etc/nginx/modsecurity.conf
cp ModSecurity/unicode.mapping /etc/nginx/

modsecurity.conf中添加crs-setup.conf的配置:

SecRuleEngine On
Include /etc/nginx/owasp/crs-setup.conf
Include /etc/nginx/owasp/rules/*.conf

在nginx的配置中开启modsecurity模块,可以放在server段或者location段内:

modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity.conf;

测试配置文件是否正确:

nginx -t -c /etc/nginx/nginx.conf

可能会报错:

2019/06/01 20:56:09 [emerg] 29985#0: "modsecurity_rules_file" directive Rules error. File: /etc/nginx/owasp/rules/REQUEST-910-IP-REPUTATION.conf. Line: 71. Column: 22. This version of ModSecurity was not compiled with GeoIP or MaxMind support.  in /etc/nginx/nginx.conf:40
nginx: configuration file /etc/nginx/nginx.conf test failed

这是因为ModSecurity中的IP检测的功能还没有添加,暂时可以先不考虑这个,直接删掉或者重命名掉不加载即可:

mv /etc/nginx/owasp/rules/REQUEST-910-IP-REPUTATION.conf /etc/nginx/owasp/rules/REQUEST-910-IP-REPUTATION.conf.bak

测试无误后重启nginx服务,务必使用restart而不是reload等操作。

三、测试

3.1 正常访问

maqian@Inspiron:~$ curl http://localhost -I
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Sat, 01 Jun 2019 13:00:38 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sat, 01 Jun 2019 12:34:27 GMT
Connection: keep-alive
ETag: "5cf270d3-264"
Accept-Ranges: bytes

返回200,正常访问。

3.2 简单SQL注入

maqian@Inspiron:~$ curl 'http://localhost/?id=1 AND 1=1' -I
HTTP/1.1 403 Forbidden
Server: nginx/1.12.2
Date: Sat, 01 Jun 2019 13:01:30 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

返回403,禁止访问。

3.3 简单xss攻击

maqian@Inspiron:~$ curl 'http://localhost/?search=<scritp>alert('xss');</script>' -I
HTTP/1.1 403 Forbidden
Server: nginx/1.12.2
Date: Sat, 01 Jun 2019 13:01:15 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

返回403,禁止访问。

四、日志

默认情况下,ModSecurity是开启了审计日志的,会把审计日志打到modsec_audit.log,以下就是上面执行xss攻击时候的日志:

---EmbUKKWv---A--
[01/Jun/2019:21:01:15 +0800] 155939407569.849497 127.0.0.1 58856 127.0.0.1 80
---EmbUKKWv---B--
HEAD /?search=<scritp>alert(xss);</script> HTTP/1.1
Host: localhost
User-Agent: curl/7.58.0
Accept: */*

---EmbUKKWv---D--

---EmbUKKWv---F--
HTTP/1.1 403
Server: nginx/1.12.2
Date: Sat, 01 Jun 2019 13:01:15 GMT
Content-Length: 169
Content-Type: text/html
Connection: keep-alive

同时nginx的日志中也有日志:

2019/06/01 21:01:15 [error] 30005#0: *3 [client 127.0.0.1] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `5' ) [file "/etc/nginx/owasp/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "79"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"]     [hostname "127.0.0.1"] [uri "/"] [unique_id "155939407569.849497"] [ref ""], client: 127.0.0.1, server: localhost, request: "HEAD /?search=<scritp>alert(xss);</script> HTTP/1.1", host: "localhost"
2019/06/01 21:01:30 [error] 30005#0: *4 [client 127.0.0.1] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `7' ) [file "/etc/nginx/owasp/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "79"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 7)"] [data ""] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"]     [hostname "127.0.0.1"] [uri "/"] [unique_id "155939409056.181076"] [ref ""], client: 127.0.0.1, server: localhost, request: "HEAD /?id=1 AND 1=1 HTTP/1.1", host: "localhost"

正式环境下,如果访问量很大,建议关闭审计日志,开启审计日志会导致以下问题:

  1. 写入大量的日志数据,会消耗磁盘容量。
  2. 大量的IO操作会影响设备的性能。

关闭审计日志需要在/etc/nginx/modsecurity.conf中添加配置:

SecAuditEngine off

五、优化

5.1 不检查静态内容

location / {
    modsecurity on;
    modsecurity_rules_file /etc/xxxx/main.conf;
    root html;
}
location ~ \.(gif|jpg|png|jpeg|svg)$ {
    root /data/images; 
}

六、参考文档

ModSecurity3_Nginx 指南

nginx下安装配置modsecurity waf防火墙(附完整编译、配置、排错、详细规则)

Nginx1.14.0+ModSecurity实现简单的WAF

最后修改:2019 年 06 月 16 日
喜欢就给我点赞吧