nginx-整合modsecurity做waf
简介
ModSecurity是一个开源的、跨平台的Web应用防火墙(WAF),被称为WAF界的“瑞士军刀”。它可以通过检查Web服务接收到的数据,以及发送出去的数据来对网站进行安全防护。
主要提供一下规则:
- SQL Injection (SQLi):阻止SQL注入
- Cross Site Scripting (XSS):阻止跨站脚本攻击
- Local File Inclusion (LFI):阻止利用本地文件包含漏洞进行攻击
- Remote File Inclusione(RFI):阻止利用远程文件包含漏洞进行攻击
- Remote Code Execution (RCE):阻止利用远程命令执行漏洞进行攻击
- PHP Code Injectiod:阻止PHP代码注入
- HTTP Protocol Violations:阻止违反HTTP协议的恶意访问
- HTTPoxy:阻止利用远程代理感染漏洞进行攻击
- Sshllshock:阻止利用Shellshock漏洞进行攻击
- Session Fixation:阻止利用Session会话ID不变的漏洞进行攻击
- Scanner Detection:阻止黑客扫描网站
- Metadata/Error Leakages:阻止源代码/错误信息泄露
- Project Honey Pot Blacklist:蜜罐项目黑名单
- GeoIP Country Blocking:根据判断IP地址归属地来进行IP阻断
开始安装
安装后续所需要的依赖:
yum install -y gcc-c++ flex bison yajl yajl-devel curl-devel curl GeoIP-devel doxygen zlib-devel pcre-devel lmdb-devel libxml2-devel ssdeep-devel lua-devel libtool autoconf automake wget epel-release openssl-devel
下载必要的文件:
- 创建目录:
mkdir -p /home/software/nginx-mod
cd /home/software/nginx-mod
-
下载ModSecurity 安装包
wget http://www.modsecurity.cn/download/modsecurity/modsecurity-v3.0.4.tar.gz
-
下载ModSecurity 和 nginx的桥接文件
wget https://codeload.github.com/SpiderLabs/ModSecurity-nginx/zip/refs/heads/master (这个可能下载下来的有问题,可以在本机电脑下载后上传) -
下载nginx 安装包
wget http://nginx.org/download/nginx-1.25.5.tar.gz
-
下载ModSecurity 核心规则文件
wget http://www.modsecurity.cn/download/corerule/owasp-modsecurity-crs-3.3-dev.zip
最后结果:
-rw-r--r--. 1 root root 260374 5月 13 2020 modsecurity-nginx-master.zip
-rw-r--r--. 1 root root 2806291 5月 13 2020 modsecurity-v3.0.4.tar.gz
-rw-r--r--. 1 root root 1244060 4月 16 22:37 nginx-1.25.5.tar.gz
-rw-r--r--. 1 root root 460374 5月 13 2020 owasp-modsecurity-crs-3.3-dev.zip
安装ModSecurity:
#解压
tar -zxvf modsecurity-v3.0.4.tar.gz
cd /home/software/nginx-mod/modsecurity-v3.0.4
#编译
sh build.sh
./configure
#安装,这一步会有点久,请耐心等待
make && make install
libtool: link: g++ -g -O2 -o rules_optimization optimization/rules_optimization-optimization.o -L/usr/lib64/ ../src/.libs/libmodsecurity.a -lcurl -lGeoIP -lrt -lxml2 -lz -lm -ldl -llua-5.1 -lpcre -lyajl
make[2]: 离开目录“/home/software/nginx-mod/modsecurity-v3.0.4/test”
make[1]: 离开目录“/home/software/nginx-mod/modsecurity-v3.0.4/test”
make[1]: 进入目录“/home/software/nginx-mod/modsecurity-v3.0.4”
make[1]: 对“all-am”无需做任何事。
make[1]: 离开目录“/home/software/nginx-mod/modsecurity-v3.0.4”
make: *** 没有规则可以创建目标“instal”。 停止。
#最后看到有上面的内容表示安装完成
安装ModSecurity-Nginx
#解压:
unzip modsecurity-nginx-master.zip
#移动到modsecurity目录下:
mv modsecurity-nginx-master /home/software/nginx-mod/modsecurity-v3.0.4/modsecurity-nginx
#现在的结构
cd /home/software/nginx-mod/modsecurity-v3.0.4
-rwxr-xr-x. 1 1000 1000 707870 5月 11 11:05 configure
-rw-r--r--. 1 root root 174749 5月 11 11:07 Makefile
-rw-r--r--. 1 1000 1000 10210 1月 13 2020 modsecurity.conf-recommended
drwxr-xr-x. 5 root root 201 5月 11 11:11 modsecurity-nginx
drwxr-xr-x. 14 1000 1000 4096 5月 11 11:14 src
...
#可以看到modsecurity-nginx文件夹在modsecurity-v3.0.4目录下
安装nginx
注:如果已经安装了nginx可以在安装的时候指定安装路径避免和原本的nginx冲突覆盖。
可以使用以下命令查看安装nginx的路径(如果是下载的二进制文件编译安装的)
./nginx -V
nginx version: nginx/1.25.5
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx-1.25.5
可以看到我的nginx版本是1.25.5,安装路径是/usr/local/nginx-1.25.5
开始安装:
#解压:
tar -zxvf nginx-1.25.5.tar.gz
#改个名字
mv nginx-1.25.5 nginx-1.25.5-install
cd nginx-1.25.5-install
#编译
./configure --prefix=/home/software/nginx-mod/nginx-1.25.5 --with-http_stub_status_module --with-http_ssl_module --with-file-aio --with-http_realip_module --add-dynamic-module=/home/software/nginx-mod/modsecurity-v3.0.4/modsecurity-nginx
#--add-dynamic-module 指定要添加的module 这里添加的是modsecurity 指定了路径
#结果:
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ using system zlib library
nginx path prefix: "/home/software/nginx-mod/nginx-1.25.5"
nginx binary file: "/home/software/nginx-mod/nginx-1.25.5/sbin/nginx"
nginx modules path: "/home/software/nginx-mod/nginx-1.25.5/modules"
nginx configuration prefix: "/home/software/nginx-mod/nginx-1.25.5/conf"
nginx configuration file: "/home/software/nginx-mod/nginx-1.25.5/conf/nginx.conf"
nginx pid file: "/home/software/nginx-mod/nginx-1.25.5/logs/nginx.pid"
nginx error log file: "/home/software/nginx-mod/nginx-1.25.5/logs/error.log"
nginx http access log file: "/home/software/nginx-mod/nginx-1.25.5/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
#如果最后出现上面的字样表示编译成功
#执行安装:
make && make install
#结果
cp objs/ngx_http_modsecurity_module.so '/home/software/nginx-mod/nginx-1.25.5/modules/ngx_http_modsecurity_module.so'
make[1]: 离开目录“/home/software/nginx-mod/nginx-1.25.5-install”
#如果出现上面的字样表示安装成功
#现在的结构
drwxr-xr-x. 13 1000 1000 4096 5月 11 11:49 modsecurity-v3.0.4
drwxr-xr-x. 12 root root 166 5月 11 14:36 nginx-1.25.5
drwxr-xr-x. 9 502 games 186 5月 11 11:52 nginx-1.25.5-install
-rw-r--r--. 1 root root 460374 5月 13 2020 owasp-modsecurity-crs-3.3-dev.zip
#进入安装好的nginx下看看
drwxr-xr-x. 3 root root 4096 5月 11 14:31 conf
drwxr-xr-x. 2 root root 40 5月 11 11:54 html
drwxr-xr-x. 2 root root 58 5月 11 14:50 logs
drwxr-xr-x. 2 root root 44 5月 11 11:54 modules
drwxr-xr-x. 2 root root 19 5月 11 11:54 sbin
开始配置相关的防火墙规则
-
将ModSecurity下的配置文件 复制到nginx.config 目录,方便后期更改配置:
mkdir -p /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity #复制核心配置文件 cp /home/software/nginx-mod/modsecurity-v3.0.4/modsecurity.conf-recommended /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/modsecurity.conf cp /home/software/nginx-mod/modsecurity-v3.0.4/unicode.mapping /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity
-
修改nginx.conf配置文件:
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; #添加了这一行,加载modsecurity模块,让nginx支持waf load_module modules/ngx_http_modsecurity_module.so; events { worker_connections 1024; } http { #开启modsecurity modsecurity on; #指定modsecurity核心配置文件 modsecurity_rules_file /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/modsecurity.conf; include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
-
启动测试是否正常加载:
#检查配置文件 ./nginx -t #启动 ./nginx #没有报错正常启动
-
现在只是搭建好,还需要打开和添加防火墙规则:
#解压下载好的规则文件 unzip owasp-modsecurity-crs-3.3-dev.zip cd owasp-modsecurity-crs-3.3-dev #配置文件 cp crs-setup.conf.example /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/crs-setup.conf #复制所有规则配置文件 cp -r rules /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/ cd /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/rules mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf 关于上面的两个文件说明: #1. 通过全局方式禁用规则,指令需加载在RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf文件中,也可创建自定义规则文件,但需先加载ModSecurity核心规则文件,再加载自定义规则文件。 #2. 通过白名单方式禁用规则,指令需加载在REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf文件中,也可创建自定义规则文件,但需先加载自定义规则文件,再加载ModSecurity核心规则文件。
-
将防火墙配置文件加载到nginx中
#打开配置: vim /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/modsecurity.conf 注释:#SecRuleEngine DetectionOnly 添加:SecRuleEngine On 注释:#SecAuditLogParts ABIJDEFHZ 添加:SecAuditLogParts ABCDEFHZ 添加防护规则文件 Include /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/crs-setup.conf Include /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/rules/*.conf
-
重启nginx测试:
./nginx -t ./nginx -s reload 测试会被拦截的请求看看是否被拦截 wget http://192.168.0.1/projectName?PHPRC=/dev/fd/0 可以看到被拦截了 返回403
查看拦截情况的日志:
#日志默认在
/var/log/modsec_audit.log
#我们监听日志文件,请求一个会被拦截的请求试试
tail -f /var/log/modsec_audit.log
#接着请求
wget http://192.168.0.1/projectName?PHPRC=/dev/fd/0
#日志打印内容
---q2JtnKPF---A--
[11/May/2024:20:27:09 +0800] 17154304293.336548 10.160.242.40 46266 192.168.0.1 443
---q2JtnKPF---B--
GET /projectName/?PHPRC=/dev/fd/0 HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
---q2JtnKPF---F--
HTTP/1.1 403
Server: nginx
Date: Sat, 11 May 2024 12:27:09 GMT
Content-Length: 146
Content-Type: text/html
Connection: keep-alive
Strict-Transport-Security: max-age=31536000; includeSubDomains
---q2JtnKPF---H--
ModSecurity: Warning. Matched "Operator `Rx' with parameter `^[\d.:]+$' against variable `REQUEST_HEADERS:Host' (Value: `192.168.0.1' ) [file "/home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "722"] [id "920350"] [rev ""] [msg "Host header is a numeric IP address"] [data "192.168.0.1"] [severity "4"] [ver "OWASP_CRS/3.2.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [hostname "192.168.0.1"] [uri "/projectName/"] [unique_id "17154304293.336548"] [ref "o0,13v42,13"]
ModSecurity: Warning. Matched "Operator `PmFromFile' with parameter `unix-shell.data' against variable `ARGS:PHPRC' (Value: `/dev/fd/0' ) [file "/home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [line "496"] [id "932160"] [rev ""] [msg "Remote Command Execution: Unix Shell Code Found"] [data "Matched Data: dev/fd/ found within ARGS:PHPRC: /dev/fd/0"] [severity "2"] [ver "OWASP_CRS/3.2.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-shell"] [tag "platform-unix"] [tag "attack-rce"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION"] [tag "WASCTC/WASC-31"] [tag "OWASP_TOP_10/A1"] [tag "PCI/6.5.2"] [hostname "192.168.0.1"] [uri "/projectName/"] [unique_id "17154304293.336548"] [ref "o1,7v17,9t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase"]
ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `8' ) [file "/home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "80"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 8)"] [data ""] [severity "2"] [ver "OWASP_CRS/3.2.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "192.168.0.1"] [uri "/projectName/"] [unique_id "17154304293.336548"] [ref ""]
时间:2024 年 5 月 11 日 17:08:16
错误码:403(Access denied)
客户端 IP:192.168.0.1
规则文件路径:/home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
规则 ID:920350
错误消息:Host header is a numeric IP address
严重性:4
规则版本:OWASP_CRS/3.2.0
标签:application-multi、language-multi、platform-multi、paranoia-level/1
主机名:127.0.0.1
请求 URI:/projectName/
请求方法:GET
等等。。。
后面几个也是差不多的
扩展针对指定url、参数配置白名单:
情况:cas项目做统一认证,在没有域名的情况下,使用ip访问会被误拦截
比如:http://192.168.0.1/cas/login?service=http%3A%2F%2F192.168.0.1%2Fproject2%2Fasb.do%3Fsysno%3D11 被modsecurity 拦截了
直接访问 http://192.168.0.1/cas/login 是正常的 那么就出现在service上,那么就可以针对uri=/cas/login 和 args=service做白名单配置
开始:
自己新建一个白名单的配置文件
cd /home/software/nginx-mod/nginx-1.25.5/conf/modsecurity/rules
vim custom-whitelist.conf
添加:
SecRule REQUEST_URI "@beginsWith /cas/login" "id:500001,phase:1,pass,nolog,ctl:ruleRemoveTargetById=949110;ARGS:service"
SecRule REQUEST_URI "@beginsWith /cas/logout" "id:500002,phase:1,pass,nolog,ctl:ruleRemoveTargetById=949110;ARGS:service"
上述规则表示,当被访问的URL为/cas/login 或者/cas/logout 开头时,选择性的只针对service参数取消ID编号为942100的规则匹配,该次请求的其他参数依旧会被该规则进行匹配校验。
#注意id不能重复
#ruleRemoveTargetById=949110 表示删除949110编号的校验,因为这边查看了日志发现是这个编号误拦截了