mod_security 入门

作者:Mick Bauer

有什么比 Web 安全更重要?无论您的防火墙多么先进,您的网络多么分隔,以及您的加密多么强大,如果您的 Web 应用程序易受攻击,这一切都将崩溃。一方面,没有什么可以替代严格的用户输入验证和其他安全编程实践。但另一方面,如果没有某种安全网,风险就太高了。

Ivan Ristic 为我们提供了这样一个安全网:他出色的 Apache 模块 mod_security 充当用户和您的 Web 应用程序之间的应用层代理。mod_security 模块可以阻止 SQL 注入、跨站脚本和其他基于输入的 Web 攻击,只需您付出最少的努力,并且对您的 Web 开发人员或用户没有任何影响。

在本文中,我将告诉您在您自己的基于 Apache 的 Web 服务器上安装和开始配置 mod_security 所需了解的内容。

为什么您需要 mod_security

篇幅不允许对 mod_security 旨在帮助缓解的全部威胁范围进行全面解释。如果您是 Web 安全新手,您的第一站应该是开放 Web 应用程序安全项目 (OWASP) 网站(请参阅在线资源),OWASP 十大最关键 Web 应用程序安全漏洞的所在地。合理的第二站是我写的Linux 服务器安全第二版第 10 章“保护 Web 服务器”,或 Ivan Ristic 写的Apache 安全

就我们这里的目的而言,只需说在 Web 服务器的不同类型的漏洞中,迄今为止最典型的是用户输入验证不足或不完整。事实上,OWASP 十大列表中的许多项实际上只是这一系列问题的子集;例如,命令注入和跨站脚本是用户输入滥用的类型。当然,用户输入不仅包括 HTTP GET 请求中请求的 URL,还包括 POST 命令中发送的数据。

mod_security 模块使您的 Apache Web 服务器能够更强大地检查和处理来自 Web 客户端的输入,然后再由等待输入的脚本或进程对其进行操作。mod_security 模块甚至允许您在 Web 服务器输出传输回客户端之前对其进行检查。我喜欢这个功能:它允许您注意服务器响应,这些响应可能表明其他过滤器已失败,并且攻击已成功!

mod_security 模块还允许您自动记录 Apache 通常不会记录的事件和会话数据。这不仅对取证目的有用,而且对微调您的 mod_security 规则也很有用。如果您创建了严格的 mod_security 过滤器,并且担心这些过滤器可能会被合法流量触发,您可以将这些过滤器设置为仅记录,而不是实际丢弃或重定向触发它们的请求。

但是等等,还有更多:mod_security 也适用于加密的 Web 流量!由于 mod_security 可以在 SSL 加密之前和 SSL 解密之后访问事务数据,因此 mod_security 可以像过滤 HTTP 流量一样有效地过滤 HTTPS 流量。

为什么您不需要 mod_security?可以说,如果您有一个“宣传册式”网站,不涉及数据库或 cgi 脚本,而只是提供静态网页,那么 mod_security 可能不值得设置的麻烦。但是,我建议,即使在这样的服务器上,mod_security 仍然可能对您有所帮助,例如,在抑制某些类型的信息收集攻击方面。请继续阅读,并自行决定。

获取和安装 mod_security

mod_security 模块在 Apache 1.3 和 Apache 2.0 上均可运行。虽然对于大多数 Linux 发行版,您需要从源代码安装 mod_security,但 Debian 有其自己的 mod_security 二进制软件包。

如果您运行 Debian,请安装软件包 mod-security-common,以及 libapache2-mod-security 或 libapache-mod-security,具体取决于您运行的是 Apache 版本 2 还是版本 1。虽然 Debian 的 mod_security 软件包适用于 mod_security 版本 1.8.7,而不是更高级的版本 1.9,但本文足够基础,同样适用于版本 1.8.7 和 1.9。

如果您运行 SUSE 或 Red Hat Enterprise Linux,您需要从 www.modsecurity.org 下载最新的源代码,并使用 apsx 或 apsx2 命令(分别是 SUSE 的 apache-devel 和 apache2-devel 软件包以及 RHEL 的 httpd-devel 软件包的一部分)编译它。一旦您安装了 apsx 或 apsx2 并获得了源代码文件 mod_security.c,您只需从包含 mod_security.c 的目录中发出以下两个命令之一

/usr/sbin/apxs -cia mod_security.c

/usr/sbin/apxs2 -cia mod_security.c

有关从源代码安装 mod_security 的更多信息,请参阅 ModSecurity 用户指南或 mod_security 源代码的 INSTALL 文件。

配置 mod_security

与其他所有 Apache 模块一样,mod_security 模块通过 Apache 1.3 中的 httpd.conf 或 Apache 2.x 中的 apache2.conf 进行控制。一方面,mod_security 的配置参数易于使用且文档齐全。但另一方面,截至本文撰写之时,没有默认配置;假设您对您的环境和 Web 安全有足够的了解,可以从头开始创建自己的配置。

事实上,只有您(和您的 Web 开发人员)知道哪些类型的输入对于您特定服务器上的 Web 应用程序是合法的。但是,如果有一个最小的默认配置可以开始使用,那不是很好吗?幸运的是,ModSecurity 用户指南中提供了一个。

本文的其余部分是对这个最小配置的剖析,它应该让您了解 mod_security 的强大功能。有关 mod_security 配置参数和更高级示例的更完整参考,请参阅本文的在线资源。

与其在一个庞大的列表中呈现整个配置,不如将其分解为可管理的部分。清单 1 包含一些基本设置。

清单 1. apache2.conf/httpd.conf 中 mod_security 参数的开头

<IfModule mod_security.c>
	SecFilterEngine On
	SecFilterDefaultAction "deny,log,status:403"
	SecFilterScanPOST On
	SecFilterCheckURLEncoding On
	SecFilterCheckUnicodeEncoding Off
	SecFilterForceByteRange 1 255

清单 1 中的第一行只是检查是否已启用 mod_security;如果未启用,则忽略后续参数。参数 SecFilterEngine 控制是否启用 mod_security 的过滤引擎。默认值为 Off,因此您需要将其显式设置为 On(这将导致 mod_security 检查所有数据)或 DynamicOnly(这将启用过滤,但告诉 mod_security 忽略对静态内容的请求(特别是,它忽略具有空处理程序的请求))。请注意,DynamicOnly 设置的行为可能与您期望的有所不同;虽然它可以节省 CPU 周期,但如果您使用 DynamicOnly,则需要进行一些测试。

SecFilterDefaultAction 非常重要。它定义了对过滤器匹配项采取的默认操作。在清单 1 中,这设置为同时记录匹配的请求,并使用状态代码 403 消息拒绝它。显然,您可以指定多个操作,以逗号分隔。

如果 SecFilterScanPOST 设置为 On,则告诉 mod_security 不仅检查 GET 请求,还检查 POST 负载。

将 SecFilterCheckURLEncoding 设置为 On 会导致检查 URL 中的十六进制编码值是否为有效值 (0-9, A-F)。

如果您的 Web 服务器理解 Unicode 并使用 UTF-8 编码,则可以将 SecFilterCheckUnicodeEncoding 设置为 On。

最后,SecFilterForceByteRange 指定 GET 请求和 POST 请求中的表单数据中允许的 ASCII 值范围。

接下来是我们的下一组参数——清单 2 显示了一些与日志记录相关的设置。

清单 2. 与日志记录相关的参数

SecUploadDir /tmp
SecUploadKeepFiles Off
SecAuditEngine RelevantOnly
SecAuditLog logs/audit_log
SecFilterDebugLog logs/modsec_debug_log
SecFilterDebugLevel 0

SecUploadDir 指定 mod_security 存储通过 POST 请求上传的文件以进行处理的位置,但除非 SecUploadKeepFiles 设置为 On,否则它实际上不会使用此位置。您可能不希望启用此功能,除非您有一个由 SecUploadApproveScript 指令指定的脚本,该脚本已准备好扫描此类文件,例如,一个调用 ClamAV 并可以将结果返回给 mod_security 的脚本。有关 SecUploadApproveScript 参数的更多信息,请参阅 ModSecurity 用户指南。

将 SecAuditEngine 设置为 On、RelevantOnly 或 DynamicOrRelevant 会启用 mod_security 强大的日志记录工具,该工具捕获的信息比 Apache 的默认日志多得多。On 会导致 mod_security 记录所有请求,RelevantOnly 仅记录触发 mod_security 过滤器的请求,DynamicOrRelevant 记录相关请求和具有非空处理程序的请求。SecAuditLog 指定 mod_security 应将日志写入的文件。

SecFilterDebugLog 很明显,指定 mod_security 应将内部调试信息记录到的文件。将 SecFilterDebugLevel 设置为 0 会关闭调试日志记录;如果您实际上遇到 mod_security 的问题,或者正在微调其配置,您可以将其设置为 1 以获取重要事件(这些事件也将写入审核日志),设置为 2 以获取信息消息,或设置为 3 以获取更详细的信息消息。

现在,终于,我们来到了 mod_security 的真正强大之处:自定义过滤器。清单 3 显示了三个这样的过滤器。

清单 3. 一些自定义过滤器

    SecFilterSelective REQUEST_METHOD
    ↪"!^(GET|HEAD)$" chain
    SecFilterSelective HTTP_Content-Type
    ↪"!(^application/x-www-form-urlencoded$|^multipart/form-data;)"

    SecFilterSelective REQUEST_METHOD "^POST$" chain
    SecFilterSelective HTTP_Content-Length "^$"

    SecFilterSelective HTTP_Transfer-Encoding "!^$"
</IfModule>

请注意过滤器组之间的空行。我插入这些是为了说明在过滤器末尾附加字符串 chain 会将其链接到下一个过滤器,这样,只有当请求首先匹配链中的所有先前过滤器时,才会评估链中的最后一个过滤器。从这个意义上讲,chain 有点像 if-then 语句。

清单 3 中的第一对过滤器检查请求是否不是 GET 或 HEAD 请求;如果不是,则检查请求是否包含除了表单数据以外的任何内容(content-type "application/x-www-form-urlencoded")或上传的文件(encoding-type "multipart/form-data"),这两种编码类型是 mod_security 可以解析的唯二类型。如果两个过滤器都匹配,即请求不是表单数据或文件,则拒绝该请求(请参阅清单 1 中的 SecFilterDefaultAction)。

请注意,我们的实际过滤器值("!^(GET|HEAD)$""!(^application/x-www-form-urlencoded$|^multipart/form-data;)")是正则表达式。除非您熟悉正则表达式,否则您不可能创建自己的自定义过滤器;如果您不熟悉,您可能想看看 Jeffrey Friedl 的精通正则表达式第二版(O'Reilly Media,2002 年)。

清单 3 中的第二对过滤器首先检查请求是否为 POST 请求。如果是,则检查 HTTP 参数 Content-Length 是否设置为 null;如果是,则拒绝该请求。POST 请求应该具有适当的长度;如果长度为 null,则几乎可以肯定地表明某种类型的攻击。

我们的最后一个示例过滤器,与前两个过滤器不同,它是一个单行过滤器,可以保护我们免受 HTTP 参数 Transfer-Encoding 的非空值的影响。换句话说,我们希望在 HTTP 请求中将 Transfer-Encoding 设置为 null,因为最常见的设置是 chunked,这实际上从不需要,但在过去与攻击有关。

最后,我们以 </IfModule 标记结尾,以指示我们已完成指定 mod_security 参数。实际上,清单 1-3 中的语句将位于一个连续的块中;我将它们分成三组只是为了便于阅读。

如果您希望将您的 mod_security 设置保存在一个特殊的文件中,例如 mod_security.conf,您可以在 httpd.conf 或 apache2.conf 中使用 include 语句,例如

Include /etc/apache2/mod_security.conf
启用 mod_security

在 httpd.conf 或 apache2.conf 中配置 mod_security 后,您就可以启用它了。对于 Apache 1.x,您的 httpd.conf 需要包含以下行

LoadModule security_module libexec/mod_security.so

并且可能还包含

AddModule mod_security.c

如果您运行 Apache 2.x,则您的 apache2.conf 文件需要以下行

LoadModule security_module modules/mod_security.so

除非您运行 Debian 并安装了其 mod_security deb 软件包,否则情况如此,在这种情况下,您只需要从命令提示符运行以下命令(以 root 身份)

a2enmod mod-security

启用 mod_security 后,您需要重新启动 Apache 才能加载模块。执行此操作后,请务必测试您的 Web 应用程序,以确保您没有通过您的 mod_security 配置对自己进行拒绝服务攻击!

结论

有了这些,您应该可以探索一些更高级的过滤器,这些过滤器专门监视您的站点不应期望看到的请求。我强烈建议您采取下一步措施;虽然我认为本文应该为您提供了一个良好的起点,但您可以在 modsecurity.org 网站上的“ModSecurity For Apache 用户指南”和其他文档中找到更强大的过滤器的示例。祝您好运,并保持安全!

本文资源: /article/8744

Mick Bauer (darth.elmo@wiremonkeys.org) 是美国最大银行之一的网络安全架构师。他是 O'Reilly 图书Linux 服务器安全第二版(以前称为使用 Linux 构建安全服务器)的作者,信息安全会议的偶尔演讲者,以及“网络工程波尔卡舞曲”的作曲家。

加载 Disqus 评论