当前位置: 首页 > 工具软件 > ModSecurity > 使用案例 >

Web 应用防火墙:Modsecurity 和核心规则集

宗政兴发
2023-12-01

Web 应用程序防火墙 (WAF) 过滤 HTTP 流量。通过将其集成到您的 Web 服务器中,您可以确保在潜在危险请求到达您的 Web 应用程序或敏感数据从您的 Web 服务器泄漏之前被阻止。通过这种方式,您可以添加一个额外的防御层,从而为您的 Web 服务器或 Web 应用程序中的零日漏洞提供额外的保护。在这篇博文中,我将提供一个教程,介绍如何在 Debian 上安装和配置 ModSecurity Web 应用程序防火墙和核心规则集。通过一些小的修改,您还可以使用本指南在 Ubuntu 或其他发行版上设置 ModSecurity。

ModSecurity是最著名的开源 Web 应用程序防火墙。ModSecurity 的未来看起来不太光明,但幸运的是Coraza WAF正在开发一种与 ModSecurity 完全兼容的替代方案。目前,Coraza 仅与 Caddy Web 服务器集成,并且没有用于 Apache 或 NGinx 的连接器,因此目前还不能用作 ModSecurity 的替代品。

虽然 ModSecurity 提供了过滤 HTTP 流量的框架,但您还需要定义要阻止的内容的规则,这就是核心规则集(CRS) 的用武之地。CRS 是一组通用规则绞盘,可通过以下方式对各种常见攻击提供保护HTTP,例如 SQL 注入、代码注入和跨站点脚本 (XSS) 攻击。

在 Debian 上安装 ModSecurity 和核心规则集

我为 ModSecurity 安装了 Apache 模块,geoip-database,可用于阻止来自某些国家的所有请求,以及 modsecurity-crs,其中包含核心规则集。我从测试中获取这个包,因为它有一个更新的版本(在撰写本文时版本为 3.3.2)。从测试中获取这个包没有风险,因为它只包含规则,不依赖于任何其他来自测试/不稳定的包。如果你喜欢更快的更新,你也可以使用不稳定的。

# apt install libapache2-mod-security2 geoip-database
# apt install -t testing modsecurity-crs

配置 ModSecurity

为了在 Apache 中加载 ModSecurity 模块,运行以下命令:

# a2enmod security2

然后将示例 ModSecurity 配置文件复制到/etc/modsecurity/modsecurity.conf

cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

现在编辑/etc/modsecurity/modsecurity.conf. 我强调一些选项:

SecRuleEngine on
SecRequestBodyLimit 536870912
SecRequestBodyNoFilesLimit 131072
SecAuditLog /var/log/apache2/modsec_audit.log
#SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
#"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
SecPcreMatchLimit 500000
SecPcreMatchLimitRecursion 500000
SecStatusEngine Off

SecRuleEngine选项控制是否应处理规则。如果设置为Off,您将完全禁用所有规则,On启用它们将阻止恶意操作。如果设置为DetectionOnly,ModSecurity 将仅记录您的规则标记的潜在恶意活动,但不会阻止它们。DetectionOnly在您真正开始阻止潜在的恶意活动之前,临时尝试规则以发现误报可能很有用。

SecAuditLog选项定义了一个包含审计日志的文件。此文件将包含有关触发 ModSecurity 规则的每个请求的详细日志。

为正则表达式库 PCRE 设置匹配限制和匹配限制递归SecPcreMatchLimitSecPcreMatchLimitRecursion将其设置得足够高将防止在分析数据时超出 PCRE 限制的错误,但将其设置得太高会使 ModSecurity 容易受到拒绝服务 (DoS) 攻击。核心规则集开发人员建议使用 50000 的值,这就是我在这里使用的值。

我更改SecRequestBodyLimit为更高的值以允许上传大文件。

我禁用了规则 200004,因为已知它会导致误报

设置SecStatusEngineOff防止 ModSecurity 将版本信息发送回其开发人员。

更改与 ModSecurity 或核心规则集相关的任何配置后,重新加载您的 Apache Web 服务器:

# systemctl reload apache2

配置核心规则集

可以通过文件配置核心规则集/etc/modsecurity/crs/crs-setup.conf

异常评分

默认情况下,核心规则集使用异常评分模式。这意味着单个规则会添加到所谓的异常分数中,最后会对其进行评估。如果异常分数超过某个阈值,则流量被阻止。您可以在 crs-setup.conf 中阅读有关此配置的更多信息,但默认配置对大多数人来说应该没问题。

设置偏执狂水平

偏执级别是一个从 1 到 4的数字,它决定了哪些规则处于活动状态并有助于异常评分。偏执程度越高,激活的规则就越多,因此核心规则集就越激进,提供更多保护,但也可能导致更多误报。默认情况下,偏执级别设置为 1。如果您使用敏感数据,建议提高偏执级别。

执行偏执级别定义了将被执行的规则,但它们的分数不会被添加到异常评分中。当 HTTP 流量达到执行偏执级别的规则时,该流量只会被记录但不会被阻止。准备提高偏执狂水平并在更高的水平上发现误报是特别有用的,而不会对您的用户造成任何干扰。

要将偏执级别设置为 1 并将执行偏执级别设置为 2,请确保您在 crs-setup.conf 中设置了以下规则:

SecAction \
  "id:900000,\
   phase:1,\
   nolog,\
   pass,\
   t:none,\
   setvar:tx.paranoia_level=1"
SecAction \
  "id:900001,\
   phase:1,\
   nolog,\
   pass,\
   t:none,\
   setvar:tx.executing_paranoia_level=2"

修复所有误报后,您可以将偏执级别提高到 2 以提高安全性。

定义允许的 HTTP 方法

默认情况下,核心规则集只允许 GET、HEAD、POST 和 OPTIONS HTTP 方法。对于许多标准站点来说,这已经足够了,但是如果您的 Web 应用程序也使用 Restful API 或 WebDAV,那么您将需要添加所需的方法。更改规则 900200,并在 crs-setup.conf 中添加注释中提到的 HTTP 方法。

SecAction \
 "id:900200,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"

禁止旧的 HTTP 版本

有一个规则可以确定您允许在 HTTP 请求中使用哪些 HTTP 版本。我取消注释并将其修改为仅允许 HTTP 版本 1.1 和 2.0。合法的浏览器和机器人总是使用这些现代 HTTP 版本之一,而旧版本通常是恶意活动的标志。

SecAction \
 "id:900230,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:'tx.allowed_http_versions=HTTP/1.1 HTTP/2 HTTP/2.0'"

屏蔽特定国家

就我个人而言,我不喜欢完全阻止来自整个国家的所有流量,因为您还会阻止合法访问者访问您的网站,但如果您想要这样做,您可以在 crs-setup.conf 中进行配置:

SecGeoLookupDB /usr/share/GeoIP/GeoIP.dat
SecAction \
 "id:900600,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:'tx.high_risk_country_codes='"

将要阻止的两个字母的国家代码添加到最后一行(两个引号之前),多个国家代码以空格分隔。

确保您已安装该软件包goeip-database

知名 Web 应用程序的核心规则集排除规则

核心规则集包含一些著名的 Web 应用程序(如 WordPress、Drupal 和 NextCloud)的规则排除项,从而减少了误报的数量。我添加了以下部分,crs-setup.conf这将允许我在需要时通过在 Apache 配置中设置 WEBAPPID 变量来启用 Apache 配置中的排除项。

SecRule WEBAPPID '@beginsWith wordpress' 'id:20000,phase:1,nolog,pass,t:none setvar:tx.crs_exclusions_wordpress=1'
SecRule WEBAPPID '@beginsWith drupal' 'id:20001,phase:1,nolog,pass,t:none setvar:tx.crs_exclusions_drupal=1'
SecRule WEBAPPID '@beginsWith dokuwiki' 'id:20002,phase:1,nolog,pass,t:none setvar:tx.crs_exclusions_dokuwiki=1'
SecRule WEBAPPID '@beginsWith nextcloud' 'id:20003,phase:1,nolog,pass,t:none setvar:tx.crs_exclusions_nextcloud=1'
SecRule WEBAPPID '@beginsWith cpanel' 'id:20004,phase:1,nolog,pass,t:none setvar:tx.crs_exclusions_cpanel=1'
SecRule WEBAPPID '@beginsWith xenforo' 'id:20005,phase:1,nolog,pass,t:none setvar:tx.crs_exclusions_xenforo=1'

为 Log4Shell 和 Spring4Shell 检测添加规则

2021 年底,在 Log4j 中检测到一个名为 Log4Shell 的严重漏洞CVE-2021-44228,它允许远程攻击者在具有易受攻击的 Log4j 版本的服务器上运行代码。虽然核心规则集提供了一些开箱即用的漏洞缓解措施,但这种保护并不完整。开发了针对 Log4Shell 的新改进检测规则。由于此错误的严重性以及它在野外被利用的事实,我强烈建议在使用 ModSecurity 版本 3.3.2(或更早版本)时手动添加此保护。较新的、尚未发布的版本应该具有开箱即用的完整保护。

首先进行修改 /etc/apache2/mods-enabled/security2.conf,使其看起来像这样:

<IfModule security2_module>
        # Default Debian dir for modsecurity's persistent data
        SecDataDir /var/cache/modsecurity

        # Include all the *.conf files in /etc/modsecurity.
        # Keeping your local configuration in that directory
        # will allow for an easy upgrade of THIS file and
        # make your life easier
        IncludeOptional /etc/modsecurity/*.conf

        # Include OWASP ModSecurity CRS rules if installed
        IncludeOptional /usr/share/modsecurity-crs/*.load
        SecRuleUpdateTargetById 932130 "REQUEST_HEADERS"
</IfModule>

然后/etc/modsecurity/99-CVE-2021-44228.conf使用以下内容创建文件:

# Generic rule against CVE-2021-44228 (Log4j / Log4Shell)
# See https://coreruleset.org/20211213/crs-and-log4j-log4shell-cve-2021-44228/
SecRule REQUEST_LINE|ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|XML://*|XML://@* "@rx (?:\${[^}]{0,4}\${|\${(?:jndi|ctx))" \
    "id:1005,\
    phase:2,\
    block,\
    t:none,t:urlDecodeUni,t:cmdline,\
    log,\
    msg:'Potential Remote Command Execution: Log4j CVE-2021-44228', \
    tag:'application-multi',\
    tag:'language-java',\
    tag:'platform-multi',\
    tag:'attack-rce',\
    tag:'OWASP_CRS',\
    tag:'capec/1000/152/137/6',\
    tag:'PCI/6.5.2',\
    tag:'paranoia-level/1',\
    ver:'OWASP_CRS/3.4.0-dev',\
    severity:'CRITICAL',\
    setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

2022 年 3 月CVE-2022-22963发布了 Spring 框架中的另一个远程代码执行 (RCE) 漏洞。核心规则集开发了一个新规则来防止此漏洞,该漏洞将包含在下一个版本中,但如果您运行的是核心规则集版本 3.3.2 或更早版本,则可以手动添加该规则。

为此,请/etc/modsecurity/99-CVE-2022-22963.conf使用以下内容创建文件:

# This rule is also triggered by the following exploit(s):
# - https://www.rapid7.com/blog/post/2022/03/30/spring4shell-zero-day-vulnerability-in-spring-framework/
# - https://www.ironcastle.net/possible-new-java-spring-framework-vulnerability-wed-mar-30th/
#
SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_BODY|REQUEST_HEADERS|XML:/*|XML://@* \
    "@rx (?:class\.module\.classLoader\.resources\.context\.parent\.pipeline|springframework\.context\.support\.FileSystemXmlApplicationContext)" \
    "id:1006,\
    phase:2,\
    block,\
    t:urlDecodeUni,\
    msg:'Remote Command Execution: Malicious class-loading payload',\
    logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
    tag:'application-multi',\
    tag:'language-java',\
    tag:'platform-multi',\
    tag:'attack-rce',\
    tag:'OWASP_CRS',\
    tag:'capec/1000/152/248',\
    tag:'PCI/6.5.2',\
    tag:'paranoia-level/2',\
    ver:'OWASP_CRS/3.4.0-dev',\
    severity:'CRITICAL',\
    setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
    setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'"

添加这些规则后,不要忘记重新加载您的 Apache 配置。

测试 ModSecurity 并检查日志

我们现在可以通过尝试滥用跨站点脚本 (XSS) 漏洞的请求轻松测试 ModSecurity:

$ curl -I "https://example.org/?search=<script>alert('CRS+Sandbox+Release')</script>"

这应该返回 HTTP 响应 403(禁止)。

每当遇到您的 ModSecurity 规则时,这将记录在您的 Apache 错误日志中。上述请求在错误日志中创建了这些消息:

[Sat Apr 09 22:22:02.716558 2022] [:error] [pid 847584:tid 140613499016960] [client client-ip:49688] [client client-ip] ModSecurity: Warning. detected XSS using libinjection. [file "/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "55"] [id "941100"] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS:search: <script>alert('CRS Sandbox Release')</script>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "example.org"] [uri "/"] [unique_id "YlHq6gKxO9SgyEd0xH9N5gADLgA"]
[Sat Apr 09 22:22:02.716969 2022] [:error] [pid 847584:tid 140613499016960] [client client-ip:49688] [client client-ip] ModSecurity: Warning. Pattern match "(?i)<script[^>]*>[\\\\s\\\\S]*?" at ARGS:search. [file "/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "82"] [id "941110"] [msg "XSS Filter - Category 1: Script Tag Vector"] [data "Matched Data: <script> found within ARGS:search: <script>alert('CRS Sandbox Release')</script>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "example.org"] [uri "/"] [unique_id "YlHq6gKxO9SgyEd0xH9N5gADLgA"]
[Sat Apr 09 22:22:02.717249 2022] [:error] [pid 847584:tid 140613499016960] [client client-ip:49688] [client client-ip] ModSecurity: Warning. Pattern match "(?i:(?:<\\\\w[\\\\s\\\\S]*[\\\\s\\\\/]|['\\"](?:[\\\\s\\\\S]*[\\\\s\\\\/])?)(?:on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found|light)|livery(?:success|error)|activate)|r(?:ag(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)|op)|i(?:s(?:c(?:hargingtimechange ..." at ARGS:search. [file "/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "199"] [id "941160"] [msg "NoScript XSS InjectionChecker: HTML Injection"] [data "Matched Data: <script found within ARGS:search: <script>alert('CRS Sandbox Release')</script>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "example.org"] [uri "/"] [unique_id "YlHq6gKxO9SgyEd0xH9N5gADLgA"]
[Sat Apr 09 22:22:02.718018 2022] [:error] [pid 847584:tid 140613499016960] [client client-ip:49688] [client client-ip] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file "/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "93"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 15)"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "example.org"] [uri "/"] [unique_id "YlHq6gKxO9SgyEd0xH9N5gADLgA"]
[Sat Apr 09 22:22:02.718596 2022] [:error] [pid 847584:tid 140613499016960] [client client-ip:49688] [client client-ip] ModSecurity: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf"] [line "91"] [id "980130"] [msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 15 - SQLI=0,XSS=15,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0): individual paranoia level scores: 15, 0, 0, 0"] [ver "OWASP_CRS/3.3.2"] [tag "event-correlation"] [hostname "example.org"] [uri "/"] [unique_id "YlHq6gKxO9SgyEd0xH9N5gADLgA"]

在前 3 行中,我们看到我们点击了不同的过滤器来检查 XSS 漏洞,更具体地说,规则 941100、941110 和 941160 都有标签paranoia-level/1

然后第四行显示我们命中了规则 949110,这导致 Web 服务器返回 HTTP 403 Forbidden 响应,因为入站异常分数 15 高于 5。然后规则 980130 为我们提供了有关评分的更多信息:我们命中了偏执级别 1 的规则得分为 15,而其他偏执级别的规则对总分的贡献为 0。我们还看到了单个攻击类型的得分:在这种情况下,所有 15 分都是由检测 XSS 攻击的规则得分的。这是使用的不同缩写的含义:

SQLISQL injection
XSScross-site scripting
RFIremote file inclusion
LFIlocal file inclusion
RCEremote code execution
PHPIPHP injection
HTTPHTTP violation
SESSsession fixation

可以在文件中找到有关符合规则的流量的更详细日志/var/log/apache2/modsec_audit.log

修复误报

首先,为了最大限度地减少误报的数量,WEBAPPID如果您正在使用核心规则集具有默认排除集的已知 Web 应用程序之一,则应设置该变量。这些网络应用程序目前是 WordPress、Drupal、Dokuwiki、Nextcloud、Xenforo 和 cPanel。您可以通过使用<a href="https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecWebAppId">SecWebAppId</a>Apache 配置中位置定义的 VirtualHost 中的选项来执行此操作。例如,如果您有 Nextcloud 使用的 VirtualHost,请在 VirtualHost 定义中进行设置:

<Virtualhost nextcloud.example.org>
    ...OTHER OPTIONS HERE...
    <IfModule security2_module>
        SecWebAppId "nextcloud"
    </IfModule>
</VirtualHost>

如果您在子目录中安装了 WordPress,请SecWebAppId在位置标签中添加。

<Location /wordpress>
    <IfModule security2_module>
        SecWebAppId "wordpress-mysite"
    </IfModule>
</Location>

如果您有多个 WordPress 站点,请为每个站点指定一个唯一的 WEBAPPID,其名称以 wordpress 开头。为每个实例添加不同的后缀,以便每个实例在 ModSecurity 中自己的应用程序命名空间中运行。

如果您仍然遇到误报,您可以使用配置指令完全禁用规则SecRuleRemoveById。我强烈建议不要全局禁用规则,而是将其删除限制在您希望删除它们的特定位置,例如通过在 Apache 配置中使用<Location><LocationMatch>标记。例如:

<LocationMatch ^/wp-admin/(admin-ajax|post)\.php>
    <IfModule security2_module>
        SecRuleRemoveById 941160 941100 941130 932105 932130 932100
    </IfModule>
</LocationMatch>

请注意不要禁用任何 949*、959* 和 980* 规则:禁用 949* 和 959* 规则将禁用所有阻止规则,而禁用 980* 规则将给您提供更少的关于正在发生的事情的信息日志。

结论

ModSecurity 和核心规则集为您的纵深防御策略中的 Web 服务器提供了额外的安全层。我强烈建议在您的服务器上实现此功能,因为它使滥用安全漏洞变得更加困难。

密切关注核心规则集博客Twitter 帐户:有时他们会针对特定的新严重漏洞发布新规则,值得将其添加到您的配置中。

 类似资料: