ModSecurity 和 nginx
nginx 是正在越来越多的网站中取代 Apache 的 Web 服务器。到目前为止,nginx 一直无法受益于 ModSecurity 提供的安全性。本文介绍如何安装 ModSecurity 并使其与 nginx 一起工作。
今年早些时候,流行的开源 Web 应用程序防火墙 ModSecurity 发布了其软件的第 3 版。第 3 版与早期版本有显著不同,因为它现在是模块化的。在第 3 版之前,ModSecurity 仅作为 Apache Web 服务器的依赖模块工作,因此其他 HTTP 应用程序无法利用 ModSecurity。现在,ModSecurity 的核心功能,即 HTTP 过滤引擎,作为一个独立的库 libModSecurity 存在,并且可以通过“连接器”集成到任何其他应用程序中。连接器是一小段代码,允许任何应用程序访问 libModSecurity。
Web 应用程序防火墙 (WAF) 是一种用于 HTTP 请求的防火墙。标准防火墙检查到达和离开网络接口的数据包,并将数据包的属性与规则列表进行比较。规则决定防火墙是允许数据包通过还是阻止它。
ModSecurity 执行与标准防火墙相同的任务,但它不是查看数据包,而是检查到达服务器的 HTTP 流量。当 HTTP 请求到达服务器时,它首先通过 ModSecurity 路由,然后再路由到目标应用程序,例如 Apache2 或 nginx。ModSecurity 将入站 HTTP 请求与规则列表进行比较。这些规则定义了恶意或有害请求的形式,因此如果传入请求与规则匹配,ModSecurity 会阻止该请求到达可能造成危害的目标应用程序。
以下示例演示了 ModSecurity 如何保护 WordPress 站点。以下 HTTP 请求是 index.php 文件的非恶意请求,如 Apache2 的日志文件中所示
GET /index.php HTTP/1.1
此请求与任何规则都不匹配,因此 ModSecurity 允许它进入 Web 服务器。
WordPress 将其大部分秘密信息(例如数据库密码)保存在名为 wp-config.php 的文件中,该文件与 index.php 文件位于同一目录中。粗心的系统管理员可能会使这个重要文件不受保护,这意味着像 Apache 或 nginx 这样的 Web 服务器会很乐意提供它。这是因为它们将提供任何未受特定配置保护的文件。这意味着以下恶意请求
GET /wp-config.php HTTP/1.1
将由 Apache 提供给任何请求者。
这就是 ModSecurity 为接受 HTTP 数据的应用程序提供保护的地方。在这种情况下,免费的核心 ModSecurity 规则集包含拒绝任何尝试访问 WordPress 安装中任何敏感文件的 HTTP 请求的规则。核心规则集还包含针对另一个流行的 CMS Drupal 的规则。
核心规则集还包含涵盖许多其他方法的规则,这些方法可以恶意构造 HTTP 请求,以获取网站的访问权限或机密信息。这些方法包括 SQL 注入、漏洞扫描、Java 和 PHP 漏洞利用等等。ModSecurity 还支持自定义规则,因此您可以通过编写自己的规则来保护您的 HTTP 应用程序免受特定目标攻击。
首先,让我们安装核心 ModSecurity 库 libModSecurity,然后让我们安装 nginx 连接器,使 nginx 能够使用 ModSecurity。在第 3 版之前,不可能将 ModSecurity 与 nginx 一起使用。如果您正在使用 Apache2,您应该继续使用 ModSecurity 第 2 版,因为 Apache2 连接器仍然存在很多错误,不建议用于生产环境。
编译和安装 libModSecurityModSecurity3 未通过任何主要 Linux 发行版的软件包管理器提供。相反,您需要克隆 ModSecurity GitHub 存储库并从其源代码构建库。但在执行此操作之前,您必须安装所有必需的构建工具和依赖项。以下软件包列表提供了 Debian 和 Ubuntu 发行版上所有必需的和大多数可选的差异:bison、flex、make、automake、gcc、pkg-config、libtool、doxygen、git、curl、zlib1g-dev、libxml2-dev、libpcre3-dev、build-essential、libyajl-dev、yajl-tools、liblmdb-dev、rdmacm-utils、libgeoip-dev、libcurl4-openssl-dev、liblua5.2-dev、libfuzzy-dev、openssl 和 libssl-dev。
请注意,其中一些软件包在基于 Red Hat 的发行版上具有不同的名称。此页面将帮助您找出具体的软件包名称。
安装这些软件包后,您可以继续编译库。这些说明与发行版无关。
首先,克隆 libModSecurity git 存储库,这将下载构建 libModSecurity 所需的所有源代码。使用 /opt/ 目录作为所有源代码的目标目录。移动到 /opt/ 目录,并使用以下命令克隆 libModSecurity git 存储库
cd /opt/
git clone https://github.com/SpiderLabs/ModSecurity
接下来,移动到克隆 ModSecurity 存储库时创建的新目录中,并切换到 v3 分支。您还需要拉取一些必要的子模块
cd ModSecurity
git checkout v3/master
git submodule init
git submodule update
现在您可以构建 libModSecurity 了。对于任何从源代码编译过程序的人来说,这应该是一个熟悉的过程。您只需要以下三个命令即可编译和安装库
sh build.sh
./configure
make
make install
如果您在普通的虚拟服务器上运行此命令,则 make
命令需要几分钟时间。libModSecurity 库现在安装在 /usr/local/modsecurity/lib/libmodsecurity.so。但是,在您安装应用程序和连接器之前,它无法执行任何操作,该连接器会将 HTTP 数据重定向到 libModSecurity 库以及一些规则。下一节将介绍安装 nginx 连接器和 ModSecurity 开发人员提供的核心规则集。
让我们通过利用 nginx 的动态加载第三方模块的功能来编译 nginx 连接器。nginx 自 1.11.5 版本以来就能够做到这一点。此版本或更高版本在大多数主要发行版的标准存储库中不可用。nginx 为 Red Hat/CentOS、Debian 和 Ubuntu 的当前稳定版本提供了存储库,其中包含支持动态模块加载的版本。此页面列出了这些存储库以及将 nginx 存储库添加到您的发行版的信息。将 nginx 存储库添加到您的存储库配置后,您需要使用您的软件包管理器安装 nginx。安装 nginx 后,使用此命令查找您安装的版本
nginx -v
获得版本号后,切换到 /opt/ 目录并从此页面下载与您的 nginx 版本匹配的源代码,并解压缩您下载的存档。
接下来,您需要克隆 ModSecurity nginx 连接器的 git 存储库。从 /opt/ 目录中,运行以下命令以克隆此存储库
git clone https://github.com/SpiderLabs/ModSecurity-nginx
现在更改为您解压缩 nginx 源代码存档时创建的新目录。在该目录中,运行以下命令以编译连接器
./configure --with-compat
↪--add-dynamic-module=/opt/ModSecurity-nginx
make modules
现在您需要使用以下命令将连接器模块复制到 nginx 模块目录中
cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
现在您已经编译了 nginx 连接器并将其复制到正确的位置,您需要配置 nginx 以使用它。此外,您还需要下载 libModSecurity 将用于过滤 HTTP 数据的规则。
首先,移动到 nginx 配置目录
cd /etc/nginx/
并将以下行添加到 /etc/nginx/nginx.conf 中的 nginx 主配置文件中
load_module modules/ngx_http_modsecurity_module.so;
您需要将此行放在以 pid
开头的行下的第一部分中,而不是放在 events
或 http
部分中。
接下来,创建一个新目录并将 ModSecurity 规则和配置加载到其中
mkdir /etc/nginx/modsec
cd /etc/nginx/modsec
git clone https://github.com/SpiderLabs/
↪owasp-modsecurity-crs.git
使用从 git 存储库下载的 ModSecurity 规则配置文件,通过使用以下命令重命名它
mv /etc/nginx/modsec/owasp-modsecurity-crs/
↪crs-setup.conf.example /etc/nginx/modsec/
↪owasp-modsecurity-crs/crs-setup.conf
现在您需要将 ModSecurity 配置文件从构建 libModSecurity 的目录复制到 /etc/nginx/modsec/。
cp /opt/ModSecurity/modsecurity.conf-recommended
↪/etc/nginx/modsec/modsecurity.conf
最后,创建一个新的配置文件,该文件加载这两个配置文件和所有规则文件。此文件将由 nginx 服务器配置块中的几行调用,这将调用 ModSecurity 的使用。使用文本编辑器创建并开始编辑此文件
nano /etc/nginx/modsec/main.conf
将以下三行添加到此文件中
Include /etc/nginx/modsec/modsecurity.conf
Include /etc/nginx/modsec/owasp-modsecurity-crs/crs-setup.conf
Include /etc/nginx/modsec/owasp-modsecurity-crs/rules/*.conf
您现在已完成构建和安装 nginx、libModSecurity、nginx 连接器和 ModSecurity 规则。现在您可以启动或重新启动 nginx 以加载新配置。如果一切正常,您在重新启动 nginx 时不会看到任何错误打印出来。
测试 ModSecurity让我们通过向“default”服务器添加几行并发出将被 ModSecurity 阻止的请求来测试 ModSecurity。“default”服务器配置是 nginx 在安装时使用的配置,并且仅在 localhost 上而不是在面向互联网的网络接口上侦听。这使得在创建任何自定义服务器配置之前启动 nginx 是安全的,因为默认配置无法从互联网访问。
默认服务器配置位于 /etc/nginx/conf.d/default.conf。使用文本编辑器打开此文件,并在 server_name
行下添加以下两行
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
再次重新启动 nginx 以加载此新配置。现在,您只需执行一个与禁止规则匹配的 HTTP 请求,即可测试 ModSecurity 是否正常工作。
ModSecurity 有两种操作模式。默认模式是它只会记录任何与禁止规则匹配的查询,但允许它们传递到应用程序。此模式允许系统管理员运行 ModSecurity 一段时间,并确保没有误报请求被阻止,从而干扰网站的正常运行。ModSecurity 将这些与禁止规则匹配的请求记录到 /var/log/modsec_audit.log。
您可以使用 curl
发出包含禁止的用户代理标头的请求来创建一个将被记录到该日志文件中的 HTTP 请求。以下命令发出一个包含标头“User-Agent: masscan”的 HTTP 请求。这是一个禁止的用户代理,因此 ModSecurity 记录它目击了一个禁止的 HTTP 请求。此命令如下所示
curl -H "User-Agent: masscan" https://127.0.0.1/
nginx 返回默认的欢迎页面作为原始 HTML,但 ModSecurity 在 /var/log/modsec_audit.log 中创建一个冗长的日志条目,该条目以
ModSecurity: Warning. Matched "Operator `PmFromFile'
↪with parameter `scanners-user-agents.data' against
&rarrhkk;variable `REQUEST_HEADERS:User-Agent' (Value: `masscan' )
这表明 ModSecurity 成功拦截并匹配了恶意 HTTP 请求。
当您想要将 ModSecurity 从记录恶意 HTTP 请求切换到主动阻止它们时,请编辑 /etc/nginx/modsec/modsecurity.conf 中的行,从
SecRuleEngine DetectionOnly
改为
SecRuleEngine On
并重新启动 nginx。现在,相同的 curl
请求将导致 403 错误
curl -H "User-Agent: masscan" https://127.0.0.1/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>
被阻止的请求也将被记录到 /var/log/modsec_audit.log。
其他 ModSecurity 连接器ModSecurity 新的模块化特性意味着任何接受或处理 HTTP 数据的应用程序都可以使用 ModSecurity 及其规则来分析 HTTP 数据。在撰写本文时,ModSecurity v3 的发布质量仅有几个月,因此没有太多额外的连接器可以使应用程序连接到 libModSecurity。
Google Summer of Code 产生了一些有趣的新连接器。第一个扩展了 Snort v3 使用 ModSecurity 规则的能力。Snort 是一种入侵检测和实时数据包嗅探和日志记录应用程序。此连接器允许 Snort 将捕获的 HTTP 数据发送到 libModSecurity,并根据 ModSecurity 规则集对其进行检查。此项目的主页是这里。
第二个 Google 赞助的连接器针对 node.js 服务器。Node.js 是一个 JavaScript 运行时,支持创建可扩展的网络应用程序。此连接器通过 ModSecurity 路由所有入站 HTTP 请求,从而为 Node 应用程序添加安全层。您可以在其主页上阅读有关此项目的更多信息。
ModSecurity v3 的发布已将 ModSecurity 从 Apache 模块转换为灵活的应用程序,任何接受 HTTP 数据的应用程序都可以轻松利用它。鉴于越来越多的人们依赖的应用程序正在从本地计算机转移到数据中心,确保这些应用程序和数据的安全性变得越来越重要。