一、 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
命令可以查看编译选项:
1 2 3 4 5 6 |
[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 功能目前一共涉及到三个东西:
- ModSecurity 的 lib 库
- ModSecurity 的 nginx 模块
- owasp 规则
克隆 ModSecurity 代码:
1 |
git clone https://github.com/SpiderLabs/ModSecurity.git |
克隆 ModSecurity-nginx 代码:
1 |
git clone https://github.com/SpiderLabs/ModSecurity-nginx.git |
克隆 owasp-modsecurity-crs 代码:
1 |
git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git |
三个代码都克隆完成后,应该存在以下三个目录:
1 2 3 4 5 6 7 |
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 目录,初始化子模块,这一步相当重要,否则后面会出错:
1 2 3 |
cd ModSecurity git submodule init git submodule update |
2.3 集成 ModSecurity 到 nginx
2.3.1 下载依赖项
依赖项注意区分系统环境,除此之外后面的流程都不再依赖系统环境。
CentOS 环境:
1 2 |
sudo yum install autoconf automake libtool gcc gcc-c++ make sudo yum install yum install prce pcre-devel openssl openssl-devel |
Ubuntu 系统:
1 2 |
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 目录:
1 2 3 |
./build.sh ./configure make && sudo make install |
因为后面的 modsecurity-nginx
和 nginx
编译都依赖 modsecurity
的 lib 库,为了方便起见,直接把编译后的库文件放到默认目录,不手动指定安装目录。
2.3.3 nginx 编译安装
如果没有安装 nginx,先下载好 nginx 代码,nginx 的编译安装参考:CentOS 源码编译安装 NGINX 。如果已经安装了 nginx,记录 nginx 当前的编译选项,参考步骤 2.1 。
nginx 是否安装不重要,不同的是如果没有安装就要先下载源代码,如果安装了就记录下编译选项。
假设安装时候的编译选项为:
1 2 |
--user=www --group=www --prefix=/usr/local/nginx-1.12.2 \ --with-http_stub_status_module --with-http_ssl_module |
进入 nginx 目录:
1 2 3 4 5 |
./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
目录下:
1 2 |
cp owasp-modsecurity-crs /etc/nginx/owasp/ -rf mv /etc/nginx/owasp/crs-setup.conf.example /etc/nginx/owasp/crs-setup.conf |
配置 ModSecurity:
1 2 |
cp ModSecurity/modsecurity.conf-recommended /etc/nginx/modsecurity.conf cp ModSecurity/unicode.mapping /etc/nginx/ |
在 modsecurity.conf
中添加 crs-setup.conf
的配置:
1 2 3 |
SecRuleEngine On Include /etc/nginx/owasp/crs-setup.conf Include /etc/nginx/owasp/rules/*.conf |
在 nginx 的配置中开启 modsecurity 模块,可以放在 server
段或者 location
段内:
1 2 |
modsecurity on; modsecurity_rules_file /etc/nginx/modsecurity.conf; |
测试配置文件是否正确:
1 |
nginx -t -c /etc/nginx/nginx.conf |
可能会报错:
1 |
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 检测的功能还没有添加,暂时可以先不考虑这个,直接删掉或者重命名掉不加载即可:
1 |
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 正常访问
1 2 3 4 5 6 7 8 9 10 |
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 注入
1 2 3 4 5 6 7 |
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 攻击
1 2 3 4 5 6 7 |
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 攻击时候的日志:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
---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 的日志中也有日志:
1 2 |
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"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [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"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [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" |
正式环境下,如果访问量很大,建议关闭审计日志,开启审计日志会导致以下问题:
- 写入大量的日志数据,会消耗磁盘容量。
- 大量的 IO 操作会影响设备的性能。
关闭审计日志需要在/etc/nginx/modsecurity.conf
中添加配置:
1 |
SecAuditEngine off |
五、优化
5.1 不检查静态内容
1 2 3 4 5 6 7 8 |
location / { modsecurity on; modsecurity_rules_file /etc/xxxx/main.conf; root html; } location ~ \.(gif|jpg|png|jpeg|svg)$ { root /data/images; } |
评论