由于一些垃圾邮件攻击等,我决定在我的网络服务器上启用 modsecurity。我安装了 Fail2Ban 并对其进行了如下配置:
摘自jail.local:
#
# Custom modsecurity
#
[modsec]
enabled = true
filter = modsec
action = iptables-multiport[name=ModSec, port="http,https"]
sendmail-buffered[name=ModSec, lines=5, [email protected]]
logpath = /var/log/apache2/modsec_audit.log
bantime = 86400
maxretry = 1
以及 modsec 过滤器:
# Fail2Ban configuration file
#
# Author: Florian Roth
[Definition]
failregex = \[.*?\]\s[\w-]*\s<HOST>\s
ignoreregex =
Modsecurity 本身的配置如下(非常标准,但如果规则命中,它也应该阻止访问):
#SecRuleEngine DetectionOnly
SecRuleEngine On
Include /usr/share/modsecurity-crs/*.conf
Include /usr/share/modsecurity-crs/base_rules/*.conf
Include /usr/share/modsecurity-crs/optional_rules/*.conf
SecRequestBodyAccess On
SecRule REQUEST_HEADERS:Content-Type "text/xml" \
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" \
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
#SecRequestBodyLimit 13107200
#SecRequestBodyNoFilesLimit 131072
#SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
#
SecRule REQBODY_ERROR "!@eq 0" \
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
#
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:400, \
msg:'Multipart request body failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
SecPcreMatchLimit 1000
SecPcreMatchLimitRecursion 1000
SecRule TX:/^MSC_/ "!@streq 0" \
"id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
SecResponseBodyAccess off
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
#SecUploadDir /opt/modsecurity/var/upload/
#SecUploadKeepFiles RelevantOnly
#SecUploadFileMode 0600
#SecDebugLog /opt/modsecurity/var/log/debug.log
#SecDebugLogLevel 3
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log
#SecAuditLogStorageDir /opt/modsecurity/var/audit/
SecArgumentSeparator &
SecCookieFormat 0
SecUnicodeMapFile unicode.mapping 20127
SecStatusEngine On
现在的问题是,fail2ban 永远不会禁止导致 modsecurity 违规的 IP。Fail2ban 日志也没有显示任何有趣的内容,只有启动消息和 jail 创建。如果发生 modsecurity 违规,fail2ban.log 中不会显示任何内容
Modsecurity 表现不错,任何目录遍历或 SQL 注入都会出现 403 错误。但是不会发生监禁(禁止 IP)。
我做错了什么?
答案1
TL;DR。日志格式已更改,您需要附加\[client [\d\.:]+\])?
:
failregex = ^%(_apache_error_client)s(?: \[client [\d\.:]+\])? ModSecurity:\s+(?:\[(?:\w+ \"[^\"]*\"|[^\]]*)\]\s*)*Access denied with code [45]\d\d (?:.*)$
libapache2-mod-security2 的日志格式已更改为拥有两次客户端。
[client 198.51.100.10:62741] [client 198.51.100.10] ModSecurity: Access denied...
in从第一个获取 IP 地址%(_apache_error_client)s
。filter.d/apache-common.conf
\[\] \[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[client <HOST>(:\d{1,5})?\]
正如 Sean Owen 注意到的,第二个需要添加到failregex
正则表达式中,但简单的 a.*
可能会被利用,因为它可以匹配任意数量的字符。\[client [\d\.:]+\])?
更具体。
详细解决方案: 更新 security2 模块的 Fail2Ban apache-security.conf 过滤器经过卡西默公司。本文添加了新的自定义filter.d/apache-security2.conf
以避免其被发行版覆盖。
答案2
我也遇到过这个问题,我在 apache-modsecurity.conf 中发现了一个错误,帮我解决了这个问题。也许这会对你有帮助。
默认的 Fail2Ban apache-modsecurity.conf failregex 如下所示:
failregex = ^%(_apache_error_client)s ModSecurity: etc...
我的 apache 错误日志如下所示:
[...time stamp...] [:error] [pid #####] [client ###.###.###.###:#####] [client ###.###.###.###] ModSecurity: etc...
注意 apache 日志中的 2 个客户端语句。我相信 Fail2Ban 只查找 1 个客户端语句。因此,.*
在 ModSecurity 前面添加允许任意数量的任意字符在第一个客户端语句之后位于 ModSecurity 之前。我很好奇是否有更好的解决方案,但那个快速修复为我解决了这个问题。
新的 Fail2Ban 正则表达式:
failregex = ^%(_apache_error_client)s .*ModSecurity: etc...
Fail2Ban 现在可以在 apache 日志中找到 modsecurity 日志条目并适当地禁止它们。
希望这对你有帮助。