Libmodsecurity 是 ModSecurity v3 项目的一个组件。该库代码库充当 ModSecurity 连接器(Connectors)的接口,接收 Web 流量并应用传统的 ModSecurity 处理。总体而言,它提供了加载/解释以 ModSecurity SecRules 格式编写的规则,并通过连接器将规则应用于你的应用程序所提供的 HTTP 内容的能力。
如果你正在寻找适用于 Apache 的 ModSecurity(即 ModSecurity v2.x),它仍在维护中,可在此处获取: 此处。
Libmodsecurity 是对 ModSecurity 平台的彻底重写。最初设计时,ModSecurity 项目只是作为一个 Apache 模块起步。随着时间推移,由于用户需求,项目已扩展为支持其他平台,包括(但不限于)Nginx 和 IIS。为了满足对更多平台支持日益增长的需求,有必要移除本项目底层的 Apache 依赖,使其更加平台无关。
基于这一目标,我们重新设计了 Libmodsecurity 的架构,使其不再依赖 Apache Web 服务器(无论是在编译时还是运行时)。这样做的一个附带效果是,用户在所有平台上都可以期待更高的性能。此外,我们借此机会为用户长期寻求的一些新功能奠定了基础。例如,我们计划在未来版本中原生支持 JSON 格式的审计日志(auditlogs),以及一系列其他功能。
“ModSecurity”分支不再包含传统上打包在一起的(面向 Nginx、Apache 和 IIS 的)传统模块逻辑。相反,该分支只包含本项目的库部分(libmodsecurity)。这个库被我们称为“连接器(Connectors)”的组件所使用,这些连接器将与你的 Web 服务器交互,并向库提供其能够理解的通用格式。每个连接器都作为独立的 GitHub 项目进行维护。例如,Nginx 连接器由 ModSecurity-nginx 项目提供(https://github.com/owasp-modsecurity/ModSecurity-nginx)。
将这些连接器分开维护,使得每个项目可以拥有不同的发布周期、问题和开发分支。此外,这也意味着当你安装 ModSecurity v3 时,只会获得你确切需要的内容,而不会包含你不会用到的额外功能。
在开始编译过程之前,请确保已安装所有必需的依赖。
有关更多信息,请参阅依赖和Git 子模块部分。
编译完成后,请确保你的构建/平台没有问题。
我们强烈建议运行单元测试和回归测试。这些测试工具位于 tests/ 子文件夹中。
作为一个动态库,libmodsecurity 必须安装在你的操作系统能够找到动态库的位置。
在类 Unix 系统上,项目使用 autotools 进行编译过程。
如果你使用的是 git 检出,请确保在构建前递归克隆仓库或初始化所有子模块。
另请参阅 Git 子模块 部分。
git clone https://github.com/owasp-modsecurity/ModSecurity ModSecurity
cd ModSecurity
此仓库使用 git 子模块。克隆后,请确保初始化并获取所有子模块:
git submodule update --init --recursive
你可以通过以下命令验证所有子模块是否已正确初始化:
git submodule status
正确初始化的子模块会显示提交哈希。
以 - 开头表示该子模块尚未初始化。
然后即可开始构建过程:
./build.sh
./configure
make
sudo make install
有关特定发行版的构建详情,请参阅我们的 Wiki: 编译方法
Windows 构建信息可在此处找到。
SecRules 中的正则表达式处理通过 Regex 工具(src/utils/regex.*)实现。
默认情况下,ModSecurity 使用 PCRE2 处理正则表达式。
这被 @rx、@rxGlobal 和 @verifyCC 等运算符使用。
构建时的行为:
--with-pcre(WITH_PCRE),可以使用旧版 PCRE。换句话说,除非显式另行配置,否则当前构建期望使用 PCRE2。
所有其他依赖都与 SecRules 或配置指令中指定的运算符相关,可能并非编译所必需。
@detectXSS 和 @detectSQL 需要 libinjection。SecRemoteRules 需要 curl。如果缺少这些库,ModSecurity 将在编译时不包含对相应运算符或指令的支持。
该仓库包含以下子模块:
others/libinjection – 用于 @detectSQLi 和 @detectXSS 运算符。
others/mbedtls(TF-PSA-Crypto 子集)– 用于加密函数和辅助工具(例如哈希、base64)。
注意: 较新的 mbedTLS v4 布局与较旧的 v3 结构不兼容。 内部结构已发生显著变化,许多组件已被移入子模块(例如 TF-PSA-Crypto)。
合并 PR #3532 后,需要运行:
git submodule update --init --recursive
这将确保获取所有必需的子模块。缺少此步骤,项目将无法成功构建。
你可以通过以下命令验证所有子模块是否已正确初始化:
git submodule status
示例输出:
bc625d5... bindings/python
2117822... others/libinjection (v4.0.0)
0fe989b... others/mbedtls (v4.1.0)
a3d4405... test/test-cases/secrules-language-tests
如果缺少某个子模块,它将显示为以 - 开头,例如:
-bc625d5... bindings/python
以 - 开头表示该子模块尚未初始化或获取。
test/test-cases/secrules-language-tests – 由 使用的共享 SecRules 一致性及回归测试套件。
others/libinjection 和 others/mbedtls 实际上对于源码构建是必需的,必须在构建前完成初始化。
若干外部库是可选的,用于启用附加功能,包括:
libcurl – SecRemoteRules 所需
LMDB – 持久化存储支持
Lua – 脚本支持
XML 库 – 扩展的 XML 处理
GeoIP(旧版)/ MaxMind
旧版 GeoIP C API(libGeoIP)已被 MaxMind 弃用且不再维护。 上游仓库已被归档,不应再用于新的部署。
相反,ModSecurity 支持积极维护的现代 MaxMind DB API(libmaxminddb)。
在配置过程中,你可能会看到类似内容:
+ GeoIP/MaxMind ....found
* (MaxMind) v1.12.2
-lmaxminddb , -I/usr/include/x86_64-linux-gnu
这表明正在使用 libmaxminddb(推荐)。
强烈建议使用 MaxMind DB 而非旧版 GeoIP 库。
库文档以 Doxygen 格式编写在代码中。要生成此文档,请使用 doxygen 工具和位于 “doc/” 子文件夹中的配置文件 “doxygen.cfg”。这将生成包含使用示例的 HTML 格式文档。
该库提供 C++ 和 C 接口。目前某些资源仅能通过 C++ 接口使用,例如创建自定义日志机制的能力(请参阅回归测试以了解这些日志机制的工作方式)。 我们的目标是让 C 和 C++ 这两种 API 提供相同的功能,如果你发现某个接口缺少了部分 API 功能,请提交 issue。
在 examples 子文件夹中,有一些关于如何使用该 API 的简单示例。 下面展示其中部分示例:
using ModSecurity::ModSecurity;
using ModSecurity::Rules;
using ModSecurity::Transaction;
ModSecurity *modsec;
ModSecurity::Rules *rules;
modsec = new ModSecurity();
rules = new Rules();
rules->loadFromUri(rules_file);
Transaction *modsecTransaction = new Transaction(modsec, rules);
modsecTransaction->processConnection("127.0.0.1");
if (modsecTransaction->intervention()) {
std::cout << "There is an intervention" << std::endl;
}
#include "modsecurity/modsecurity.h"
#include "modsecurity/transaction.h"
char main_rule_uri[] = "basic_rules.conf";
int main (int argc, char **argv)
{
ModSecurity *modsec = NULL;
Transaction *transaction = NULL;
Rules *rules = NULL;
modsec = msc_init();
rules = msc_create_rules_set();
msc_rules_add_file(rules, main_rule_uri);
transaction = msc_new_transaction(modsec, rules);
msc_process_connection(transaction, "127.0.0.1");
msc_process_uri(transaction, "http://www.modsecurity.org/test?key1=value1&key2=value2&key3=value3&test=args&test=test");
msc_process_request_headers(transaction);
msc_process_request_body(transaction);
msc_process_response_headers(transaction);
msc_process_response_body(transaction);
return 0;
}
我们非常欢迎你为这个项目做出贡献,并期待围绕 ModSecurity 这一新版本发展社区。感兴趣的领域包括:新功能、修复、错误报告、对新手用户的支持,或任何你愿意提供帮助的事情。
我们希望你的补丁能够通过 GitHub 基础设施提交,以方便我们的审查工作和 QA 集成。GitHub 提供了关于如何执行“Pull Requests”的优秀文档,更多信息请访问:https://help.github.com/articles/using-pull-requests/
请遵守编码风格。Pull requests 可以包含多个提交,但每个提交应只提供一个修复或一项功能。请不要更改目标工作范围之外的任何内容(例如,你顺手经过的某个函数中的编码风格)。有关本项目使用的编码风格的更多信息,请查看:https://www.chromium.org/blink/coding-style
请提供说明性的提交信息。你的第一行应给出补丁的要点,第三行及以后给出关于补丁的更详细解释/技术细节。补丁说明在审查过程中非常有价值。
在我们的代码中,有各种标记为 TODO 或 FIXME 的项目可能需要你关注。通过 grep 检查项目列表:
$ cd /path/to/modsecurity-nginx
$ egrep -Rin "TODO|FIXME" -R *
TODO 列表也作为 Doxygen 文档的一部分提供。
除了手动测试之外,我们强烈建议你使用我们的回归测试和单元测试。如果你实现了某个运算符,别忘了为它创建单元测试。如果你实现了其他任何功能,鼓励你为其开发配套的回归测试。
回归测试和单元测试工具是原生的,不需要任何外部工具或脚本,但你需要从其他仓库获取测试用例,因为这些测试用例与 ModSecurity 的其他版本共享,那些仓库是 git 子模块。要获取子模块仓库并运行这些工具,请执行以下列出的命令:
$ cd /path/to/your/ModSecurity
$ git submodule update --init --recursive
$ make check
在开始调试过程之前,请确认你的 bug 所在位置。问题可能出在你的连接器上,也可能出在 libmodsecurity 中。为了确定 bug 的位置,建议你编写一个能够重现 bug 场景的回归测试。如果 bug 可以通过回归测试工具复现,那么调试起来会简单得多,并且能够确保它不再发生。在 Linux 上,建议任何进行调试的人按需使用 gdb 和/或 valgrind。
在配置/编译期间,你可能希望禁用编译器优化,使你的“back traces”(回溯信息)包含可读的数据。使用 CFLAGS 禁用编译优化参数:
$ export CFLAGS="-g -O0"
$ ./build.sh
$ ./configure --enable-assertions=yes
$ make
$ sudo make install
“断言使我们能够记录假设,并在开发过程中尽早发现违规。更重要的是,断言使我们能够以最少的努力发现违规。” https://dl.acm.org/doi/pdf/10.1145/240964.240969
建议在适用之处使用断言,并在测试和调试工作流中使用 '--enable-assertions=yes' 启用它们。
源码树中包含一个基准测试工具(Benchmark),可帮助衡量库的性能。该工具位于 test/benchmark/ 目录中。构建过程也会在此处生成二进制文件,因此编译完成后你就拥有了该工具。
要运行,只需输入:
cd test/benchmark
$ ./benchmark
Doing 1000000 transactions...
你也可以传入一个较小的值:
$ ./benchmark 1000
Doing 1000 transactions...
测量时间:
$ time ./benchmark 1000
Doing 1000 transactions...
real 0m0.351s
user 0m0.337s
sys 0m0.022s
这非常快,因为基准测试使用的是最小的 modsecurity.conf.default 配置,其中包含的规则不多:
$ cat basic_rules.conf
Include "../../modsecurity.conf-recommended"
要使用真实规则进行测量,请运行同一目录中的下载脚本之一:
$ ./download-owasp-v3-rules.sh
Cloning into 'owasp-v3'...
remote: Enumerating objects: 33007, done.
remote: Counting objects: 100% (2581/2581), done.
remote: Compressing objects: 100% (907/907), done.
remote: Total 33007 (delta 2151), reused 2004 (delta 1638), pack-reused 30426
Receiving objects: 100% (33007/33007), 9.02 MiB | 16.21 MiB/s, done.
Resolving deltas: 100% (25927/25927), done.
Switched to a new branch 'tag3.0.2'
/path/to/ModSecurity/test/benchmark
Done.
$ cat basic_rules.conf
Include "../../modsecurity.conf-recommended"
Include "owasp-v3/crs-setup.conf.example"
Include "owasp-v3/rules/*.conf"
现在该命令会给出高得多的数值。
该工具是一个直接包装库的应用程序。它创建一个 ModSecurity 实例和一个 RuleSet 实例,然后根据指定的数字运行循环。在此循环中,它创建一个 Transaction 对象来模拟真实的 HTTP 事务。
每个事务都是一个带有一些 GET 参数的 HTTP/1.1 GET 请求。添加常见请求头,然后是响应头和 XML 请求体。在各个阶段之间,工具会检查是否发生了干预。所有事务都使用相同的数据创建。
请注意,该工具不会调用最后一个阶段(日志记录)。
如果你想尝试使用不同的规则集,请记得重置 basic_rules.conf。
如果你遇到配置问题,或者某些功能没有按预期工作,请使用 ModSecurity 用户邮件列表。我们也欢迎在 GitHub 上提交 issue,但我们更希望用户先在邮件列表上提问,这样你可以接触到整个社区。另外,在提交新 issue 之前,别忘了查找是否已有相关 issue。
如果你打算在 GitHub 上提交新 issue,别忘了告诉我们你的 libmodsecurity 版本,以及特定连接器(如果有)的版本。
请不要公开任何安全问题。请通过 [email protected] 联系我们报告问题。问题修复后,我们会给予你致谢。
我们愿意通过邮件列表与社区讨论任何新功能请求。你也可以随时在 GitHub 上提交 issue 来请求新功能。在提交新 issue 之前,请检查是否已有关于同一主题的 issue。
libModSecurity 的设计允许与各种绑定(bindings)集成。我们努力避免破坏 API [二进制] 兼容性,以便于与可能的绑定集成。目前,社区维护着几个值得注意的项目:
我们希望能够及时将我们的软件包发布到各发行版中,所以如果你作为打包者有任何需要帮助的地方,请告诉我们。
ModSecurity 的开发由 Trustwave 赞助。赞助将于 2024 年 7 月 1 日结束。更多信息可在此处找到:https://www.trustwave.com/en-us/resources/security-resources/software-updates/end-of-sale-and-trustwave-support-for-modsecurity-web-application-firewall/
make checkbindings/python – ModSecurity 的 Python 绑定(核心库编译不需要)。