ModSecurity3_Nginx 指南
如何在企业中应用ModSecurity,整理相关有用的要点,用于理解和调试
一、介绍
image.pngModSecurity
一开始有上图这哥们为了保护几个web应用程序而创建的,通过嵌入到web容器中,分析数据,阻挡恶意攻击,最初是Apache HTTP
的插件。
- 2004年,ModSecurity开始商业化
- 2006年,Thinking Stone 被Breach Security收购
- 2006年,ModSecurity2.0发布
- 2010年,Trustwave收购Breach Security
- 2017年,ModSecurity3.0发布,支持Nginx
作为WAF产品,ModSecurity
专门关注HTTP流量,当发出HTTP请求时,ModSecurity
检查请求的所有部分,如果请求被认为是恶意的,它可以被阻止、记录或同时记录,这取决于配置。
ModSecurity3.0 新的体系结构
image.png-
ModSecurity
之前的版本中,在nginx中的兼容性很差,,这是因为ModSecurity
被包裹在一个完整的版本的Apache HTTP服务器,它提供了一个兼容性层ModSecurity非常严重依赖于Apache
-
ModSecurity 3 0
是一个完全重新改写,完美兼容nginx
,无需Apache
。 - 新的3.0版本中,将核心功能转移到了名为
libmodsecurity
的独立引擎中,此引擎通过nginx连接器连接到nginx,是nginx的一个组件,同时Apache
也有单独的连接器 -
NGINX
的ModSecurity
动态模块将libmodsecurity
和NGINX连接器
组合在一个包中。(也支持静态编译) -
NGINX Plus
发行版包含编译后的动态模块NGINX
开源用户每次更改NGINX
版本时都必须编译ModSecurity
源代码(nginx plus是付费产品) - 新版本比老版本更新更快,更加稳定,并且得到了
nginx、Inc和Trustwave
等团队的积极支持
警告说明
ModSecurity3.0
暂时还没有与上一个版本ModSecurity2.9
进行功能对比,需要注意一下限制:
- 不支持检查响应体的规则,如果配置中包含这些规则,则会被忽略,nginx的
sub_filter
指令可以用来检查和重写响应数据,OWASP中相关规则是95x。 - 不支持OWASP核心规则集DDoS规则,
REQUEST-912-DOS- PROTECTION.conf
,nginx本身支持配置DDoS限制 - 不支持在审计日志中包含请求和响应主体
- 一些指定没有实现,尝试使用会报错,ModSecurity参考手册列出了
ModSecurity
中所有可用的指令,以及libModSecurity
是否支持这些指令
二、安装ModSecurity
使用nginx plus的好处
ModSecurity 3.0
for NGINX Plus被称为NGINX WAF
,商业订阅有很多好处:
- 无需自己编译
ModSecurity
动态模块;NGINX, Inc
为您提供预编译模块,省时省力 -
NGINX, Inc
对动态模块进行了广泛的测试,所以您知道它适合于生产使用 -
NGINX, Inc
持续跟踪更改,并针对每一个重要的更改和安全漏洞更新模块 -
NGINX Plus
的每个新版本都包含了一个动态模块的新版本,所以你可以升级而不必重新编译ModSecurity
- 通过安装
ModSecurity
和OWASP
核心规则集,以及故障排除和调试帮助,您可以获得24x7支持
Nginx Plus
提供一周的试用时间。
nginx源码编译
在nginx 1.11.5或更高版本中,可以直接通过编译动态模块,不需要重新编译nginx二进制文件,直接将动态模块加载到nginx配置中进行引用。
1、从nginx官方存储库下载安装
从官网下载源码:https://nginx.org
nginx版本1.11.5或更高版本(使用nginx动态模块)
2、安装依赖包
yum install epel-release
yum install gcc-c++ flex bison yajl yajl-devel curl-devel curl GeoIP-devel doxygen zlib-devel pcre pcre-devel libxml2 libxml2-devel autoconf automake lmdb-devel ssdeep-devel ssdeep-libs lua-devel libmaxminddb-devel git
3、下载编译libmodsecurity
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
编译时间大概15分钟,取决于系统性能
4、下载nginx连接器源码,并编译成动态模块
- 克隆镜像
git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
- 确定nginx安装的版本
nginx -v
nginx version: nginx/1.13.7
- 下载NGINX安装版本对应的源代码(即使只编译动态模块,也需要完整的源代码):
wget http://nginx.org/download/nginx-1.13.7.tar.gz
tar zxvf nginx-1.13.7.tar.gz
- 编译动态模块,并复制模块到标准目录
cd nginx-1.13.7
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx $ make modules
cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules
5、加载nginx连机器动态模块
load_module modules/ngx_http_modsecurity_module.so;
nginx在读取配置时,会加载动态模块
Nginx Plus 安装说明
介绍如何安装NGINX web application firewall
(WAF)。NGINX WAF
构建在ModSecurity 3.0
之上
NGINX WAF
可以作为一个下载的动态模块提供给NGINX Plus
客户,购买或开始免费试用NGINX WAF
先决条件:https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-plus/
安装Nginx WAF
- 直接通过包管理器安装
yum install nginx-plus-module-modsecurity
- 加载动态模块
load_module modules/ngx_http_modsecurity_module.so;
- 验证模块是否加载成功
nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
验证安装
配置本地demo程序
server {
listen localhost:8085;
location / {
default_type text/plain;
return 200 "Thank you for requesting ${request_uri}\n";
}
}
测试
nginx -s reload
curl -D - http://localhost:8085 HTTP/1.1 200 OK
#Server: nginx/1.11.10
#Date: Wed, 3 May 2017 08:55:29 GMT Content-Type: text/plain Content-Length: 27
#Connection: keep-alive
Thank you for requesting /
配置nginx反向代理
server {
listen 80;
location / {
proxy_pass http://localhost:8085; proxy_set_header Host $host;
}
}
测试
nginx -s reload
curl -D - http://localhost HTTP/1.1 200 OK
#Server: nginx/1.11.10
#Date: Wed, 3 May 2017 08:58:02 GMT Content-Type: text/plain Content-Length: 27
#Connection: keep-alive
Thank you for requesting /
开启SecRuleEngine,并且测试
# A test rule
SecRule ARGS:testparam "@contains test" "id:1234,deny,log,status:403"
三、安装OWASP Core Rule Set
CRS文件和目录结构
CRS的主配置文件定义了异常评分阈值、偏执级别和其他重要的ModSecurity配置
规则/ 目录包含组织成不同文件的规则,每个文件都有一个分配给它的编号
-
90x文件:
排除误报 -
91x文件:
检测恶意客户端规则 -
92x文件:
检测违反协议的规则 -
93x和94x文件:
检测运行程序攻击(SQL)或命令执行攻击规则 -
95x文件:
检测出站数据泄露规则,nginx和nginx plus不支持 -
.data 文件:
规则使用的数据
异常得分
CRS使用可配置的异常计分模型,每条触发的规则都会增加异常分数,如果分数超过配置的异常阈值,则事务被阻塞,异常级别如下:
-
Critical:
异常得分5,表示可能应用程序攻击,主要由93x 94x文件生成。 -
Error:
异常得分4,表示可能数据泄露,主要有95x文件生成,暂不支持nginx和nginx plus。 -
Warning:
异常得分3,表示可能恶意客户端,主要由91x文件生成的。 -
Notice:
异常得分2,表示可能违反协议,主要由92x文件生成。
默认情况下,CRS阻塞所有异常值为5或更高的入站流量,意味着任何引发事务的关键规则都将被丢弃,三次或更多的通知级违规也会导致事务被阻塞。
使用Nikto工具
使用Nikto
扫描工具生成恶意请求
git clone https://github.com/sullo/nikto Cloning into 'nikto'...
cd nikto
perl program/nikto.pl -h localhost
- Nikto v2.1.6
...
+ 7531 requests: 0 error(s) and 324 item(s) reported on remote host
接下来,我们启用CRS,然后测试它如何阻塞Nikto的大多数请求,从而减少报告的项目数量
安装并启动OWASP CRS
wget https://github.com/SpiderLabs/owasp-modsecurity-crs/archive/ v3.0.0.tar.gz
tar -xzvf v3.0.0.tar.gz
mv owasp-modsecurity-crs-3.0.0 /usr/local
cd /usr/local/owasp-modsecurity-crs-3.0.0
cp crs-setup.conf.example crs-setup.conf
添加包括指令在主ModSecurity配置文件/etc/nginx/modsec/main
# Include the recommended configuration
Include /etc/nginx/modsec/modsecurity.conf
# OWASP CRS v3 rules
Include /usr/local/owasp-modsecurity-crs-3.0.0/crs-setup.conf Include /usr/local/owasp-modsecurity-crs-3.0.0/rules/*.conf
nginx -s reload
Testing the CRS
了解CRS中的规则如何基于请求的特定特征来阻止Nikto
的请求,我们的最终目标是显示CRS阻止Nikto
的所有请求,这样Nikto
检测到的所有漏洞都不会被攻击者利用
基于用户代理头禁用请求阻塞
CRS识别来自扫描仪(包括Nikto)的请求,通过检查用户代理报头,CRS被预先配置为阻止具有Nikto
默认用户代理报头的请求。
curl -H "User-Agent: Nikto" http://localhost/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.11.10</center>
</body>
</html>
可以从日志中得知是关联了哪个规则集REQUEST-913-SCANNER- DETECTION.conf
消除对易受攻击文件的请求
当我们对web应用程序重新运行Nikto时,我们看到只有116个Nikto请求到达应用服务器,而没有启用CRS时只有324个,这表明CRS保护我们的应用程序免受Nikto请求暴露的大部分漏洞的影响
perl program/nikto.pl -h localhost
...
+ 7531 requests: 0 error(s) and 116 item(s) reported on remote host
可以通过在program/ nikto中添加-sitefile来更好地了解实际漏洞可能存在的地方,从而禁用这些请求。
# Default plug-in macros
# Remove plug-ins designed to be run standalone
@@EXTRAS=dictionary;siebel;embedded
@@DEFAULT=@@ALL;-@@EXTRAS;tests(report:500);-sitefiles
使用XSS尝试阻塞请求
perl program/nikto.pl -h localhost
- Nikto v2.1.6
...
+ 7435 requests: 0 error(s) and 26 item(s) reported on remote host
这26项中的大多数出现是因为OWASP CRS当前没有配置为阻止请求URL中包含XSS尝试的请求
<script>alert('Vulnerable')</script>
为了阻止尝试XSS的请求,在CRS的XSS应用程序攻击规则集request-941-Application-Attack-xsd.conf
中,通过在每个规则的变量列表的开头添加REQUEST_URI
,编辑规则941160和941320:
SecRule REQUEST_URI|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/ ...
##重新加载nginx
nginx -s reload
重新运行nikto,会发现items变少了,然后根据日志信息,重新优化规则集
不支持检查响应体,因此配置这样的规则没有效果
四、安装Trustwave SpiderLabs 商业安全规则集
除了OWASP CRS
之外,Trustwave SpiderLabs
商业规则集还提供了其他保护,例如针对WordPress、Joomla、SharePoint
和其他应用程序的特定规则集。
image.png本章介绍Trustwave SpiderLabs商业规则集的安装,以安装ModSecurity的基本配置为基础,展示如何配置Trustwave SpiderLabs规则来保护创建的演示web应用程序
先决条件
- 购买Trustware SpiderLabs
- 安装部署ModSecurity和nginx反向代理系统
配置Trust SpiderLabs规则
购买规则后,可以直接登入modsecurity的dashboard,然后在门户上定制Trustwate SpiderLabs规则,与OWASP CRS相比通过这个仪表盘简化了配置。
- 通过ModSecurity的SecRemoteRules功能,直接从互联网自动下载规则
- 直接在dashboard上GUI界面启用或禁用规则,而不需要在ModSecurity配置文件中去修改
dashboard.modsecurity,org
需要账号密码登入,无法注册,需要付费购买。
配置向导
为web系统配置waf
- 登入ModSecurity Dashboard,并启动配置向导
- 创建一个profile,启动与应用程序相关的规则
- 在ModSecurity配置中添加SecRemoteRules指令,需要使用license下载规则
Include "/etc/nginx/modsec/modsecurity.conf"
SecRemoteRules license-key https://url
- 默认Trustwave SpiderLabs规则只检测恶意请求,不进行阻止,需要开启一下功能
SecDefaultAction "phase:2,log,auditlog,deny,status:403"
SecDefaultAction "phase:1,log,auditlog,deny,status:403"
-
nginx -s reload
当从远程服务器下载规则时,重新加载需要时间 - 一旦向导报告NGINX下载了规则,您就可以关闭向导并开始测试规则
从Trustwave SpiderLabs下载规则需要注意一下几点
- 每次重新加载NGINX配置或重启NGINX时,规则都是从远程服务器上新下载的,
SecRemoteRulesFailAction
指令支持两个值Abort
会强制NGINX的重载或重启失败,Warn
会让NGINX的重载或重启成功,但是没有远程规则支持 - 下载规则需要一些时间,这会延迟重新加载或重新启动操作
- 每个SecRemoteRules定义会导致一个单独的下载,进一步增加重新加载/重启时间,以避免出现这种情况,尽量减少SecRemoteRules定义的数量。
- 合并规则从不同的上下文中(http、server、location)还增加了时间重新加载/重启操作并消耗大量的CPU,定义的规则尽量最小化,尽量将所有规则放在单一的域(http、server、location)中
Trustwave SpiderLabs规则集包含16000多条用于保护各种应用程序的规则,规则越多,WAF的性能就越差,因此只启用与应用程序相关的规则非常重要
限制
不支持检查响应体
五、开启项目蜜罐
Project Honeypot
维护一个已知恶意IP地址的列表,免费提供给公共ModSecurity
与Project Honeypot
集成,可以自动屏蔽Project Honeypot
列表上的IP地址,这个过程称为IP信誉
蜜罐是如何工作的
项目蜜罐是一个社区维护的IP地址在线数据库,怀疑是垃圾邮件发送者或机器人,每个IP地址被分配一个威胁得分在0到255之间;数字越高,IP地址越有可能是恶意的。
- Honeypot是网站上的一个虚假页面,当机器人扫描网站时就会显示出来,但普通人用浏览器访问网站时是看不到的
- 当扫描器跟随蜜罐链接并尝试与页面交互时(例如,获取一个嵌入式蜜罐电子邮件地址),IP地址将被添加到数据库中
- 项目蜜罐查找是在接收到HTTP请求时实时完成的,因此启用此功能可能会降低性能,但缓存结果是为了最小化性能影响,在将
Project Honeypot
集成到生产环境之前,请务必测试它对应用程序的潜在性能影响
搭建蜜罐
要开始使用项目蜜罐,请使用项目蜜罐提供的脚本在您的站点上设置一个蜜罐:
- 注册一个免费项目蜜罐账户地址
- 设置蜜罐-项目蜜罐提供蜜罐脚本在
PHP, Python, ASP
,和一些其他语言 - 下载蜜罐脚本
测试php
server {
server_name www.example.com;
location ~ \.php$ {
modsecurity off;
root /code;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass localhost:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_ script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Notes:
- 将www.example.com 替换你在Honeyport注册的域名
- 需要在蜜罐脚本上禁用ModSecurity,这样才能正常工作
- 在/目录中,替换为蜜罐脚本目录
- 安装脚本后,在web浏览器中访问它并单击激活链接来激活蜜罐
将蜜罐链接添加到所有页面
为了捕捉机器人和扫描器,在每个页面上插入一个到蜜罐脚本的链接,这个链接对于使用web浏览器的普通人是不可见的,但是对于机器人和扫描器是可见的,我们使用sub_filter指令将链接添加到每个页面的底部:
location / {
proxy_set_header Host $host;
proxy_pass http://my_upstream;
sub_filter '</html>'
'<a href="http://www.example.com/test.php">
<!-- hightest --></a></html>';
}
在核心规则集中启用IP信誉
- 请求项目蜜罐http:BL访问密钥
- 在/usr/local/ wasp-modsecurity-cr -3.0.0/cr -setup.conf文件中,根据安装OWASP核心规则集,找到
SecHttpBlKey
块:
SecHttpBlKey my_api_key SecAction "id:900500,\
phase:1,\
nolog,\
pass,\
t:none,\
:tx.block_search_ip=0,\ ##禁用了block_search_ip,不阻止搜索引擎爬行器
setvar:tx.block_suspicious_ip=1,\
setvar:tx.block_harvester_ip=1,\
setvar:tx.block_spammer_ip=1"
- 重新加载配置以使更改生效
此时,项目蜜罐已完全启用,ModSecurity对所有HTTP请求查询项目蜜罐以最小化性能影响,只有来自给定IP地址的第一个请求被发送到项目蜜罐,查询结果被缓存
验证测试
自定义规则添加到/etc/nginx/modsec/main.conf
它将作为请求的一部分传入的IP地址参数的值发送给Project Honeypot
SecRule ARGS:IP "@rbl dnsbl.httpbl.org" "phase:1,id:171,t:none,deny, nolog,auditlog,msg:'RBL Match for SPAM Source'
运行curl命令来测试规则,如果IP地址已经被加入到蜜罐中,这个请求将被阻塞,状态码403
结论
Project Honeypot
是一个非常有用的工具,可以自动屏蔽已知的恶意IP地址
六、日志
- Audit log:提供关于事务和为什么被阻塞的详细日志
- Debug log:提供所有事务的操作信息
审计日志
ModSecurity
会记录出发告警或错误日志,以及导致5xx和4xx响应的事务,不记录404,ModSecurity
审计日志划分为以下几个部分:
阶段 | 描述 |
---|---|
A | 审计日志标题 |
B | 请求头 |
C | 请求体 |
D | 保留 |
E | 响应体 |
F | 响应头 |
G | 保留 |
H | 审计日志流,包含其他数据 |
I | 紧凑的请求主体替代C阶段部分,不包含文件 |
J | 文件上传信息 |
K | 包含于事务匹配的所有规则列表 |
Z | 最后的边界 |
触发审计日志的条目的每个事物记录,都将记录在上述指定部分,记录哪些阶段可以选择性配置
配置审计日志
默认审计日志配置文件:/etc/nginx/modsec/modsecurity.conf
SecAuditEngine RelevantOnly
控制选项
- Off:关闭审计日志
- On:记录所有事务日志,一般配合debugging使用
- RelevantOnly:只记录触发警告、错误的事务,或者拥有与
SecAuditLogRelevantStatus
指令相匹配的状态指令
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogRelevantStatus
如果SecAuditEngine
被设置为RelevantOnly
,那么这个指令将控制应该记录哪些HTTP响应状态代码。它是基于正则表达式的,上面的值将记录所有5xx和4xx响应,不包括404s
SecAuditLogParts ABIJDEFHZ
SecAuditLogParts
控制访问日志中应该包含哪些部分,只选择需要的部分,减少审计日志的大小
调试日志
debug log主要用于modscurity的调试,调试日志包含了modsecurity对事务的所有操作,调试日志列出了规则ID,可以根据规则ID进行快速查找故障
[4] (Rule: 1234) Executing operator "Contains" with param "test" against ARGS:testparam.
[9] Target value: "test" (Variable: ARGS:testparam) [9] Matched vars updated.
[4] Running [independent] (non-disruptive) action: log [9] Saving transaction to logs
[4] Rule returned 1.
[9] (SecDefaultAction) Running action: log
[9] Saving transaction to logs
[9] (SecDefaultAction) Running action: auditlog
[4] (SecDefaultAction) ignoring action: pass (rule contains a disruptive action)
[4] Running (non-disruptive) action: auditlog [4] Running (disruptive) action: deny
配置调试日志
默认调试日志禁用,因为会造成大量日志,影响系统运行,配置文件/etc/nginx/modsec/ modsecurity.conf
SecDebugLog /var/log/modsec_debug.log
SecDebugLogLevel 9
- 指定调试日志配置路径
- 设置调试日志记录级别,0-9表示需要记录的信息级别,9为最详细
七、在生产环境中使用ModSecurity的注意点
将ModSecurity部署应用到生产环境之前,需要完成以下几点配置
调优以最小化原则为准
- 确保ModSecurity在阻塞模式下运行
- 确保启用审计日志
- 阈值调到1000
SecAction \ "id:900110,\
phase:1,\ß
nolog,\
pass,\
t:none,\ setvar:tx.inbound_anomaly_score_threshold=1000,\
setvar:tx.outbound_anomaly_score_threshold=1000"
- 监控审计日志中的误报,并通过在
modsecurity.conf
中添加SecRemoveRuleByID
来防止误报
SecRemoveRuleByID rule-id
- 运行并查看误报,如果没有误报,则将异常阈值降低一半,重复此过程,直到异常阈值恢复默认的5
禁用审计日志
默认ModSecurity配置中启用了审计日志记录,但是在生产环境中需要禁用,有如下原因:
- 审计日志对ModSecurity性能有较大影响
- 日志文件增长较快,容易耗尽磁盘空间
禁用审计日志:
SecAuditEngine off
通过使用Nginx
原生的错误日志记录功能,记录所有被阻塞的事务(ModSecurity必须处于阻塞模式,否则没日志)
error_log logs/error.log error
不检查静态内容
分离出静态图像文件,以便ModSecurity不检查:
server {
listen 80;
location / { modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf; proxy_pass http://localhost:8085;
proxy_set_header Host $host;
}
location ~ \.(gif|jpg|png|jpeg|svg)$ {
root /data/images;
}
}
建议对静态文件设置proxy_cache
Nginx限制DDOS和限制速率
ModSecurity
动态模块目前不支持内置的CRS规则DDoS mitigation (REQUEST-912-DOS-PROTECTION.conf),但是静态编译的支持。
举例:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
listen 80;
location / {
limit_req zone=mylimit;
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf; proxy_pass http://localhost:8085;
proxy_set_header Host $host;
}
}
其他注意点
下面是一些在你使用ModSecurity进行生产时需要考虑的提示和技巧:
- 做好CPU扩展或服务器负载均衡:如果CPU始终超过50%,可以考虑扩展CPU,启用更多内核运行更多nginx工作进程,或者部署多台nignx负载。
- 选择需要使用的
ModSecurity
规则:精简OWASP的规则,不启用不必要的规则,它将增加cpu利用率,并且影响延迟和误报。(比如java程序则不需要php相关规则)。 - 添加
nginx
静态内容缓存proxy_cache
:因为请求检查在缓存检查之前。 - 保持最新的安全漏洞:
ModSecurity
可以阻止大范围攻击,但是它不能替代主动监视安全漏洞,需要定期更新和人工添加规则
完成以上配置,可以提高ModSecurity使用中的性能,减少误报,充分利用ModSecurity和nginx