1. 项目概述与核心价值
最近在整理安全运维的实战笔记,发现很多刚接触Web应用防火墙的朋友,对WAF的理解还停留在“一个能防攻击的盒子”这种模糊概念上。真正要理解WAF,尤其是开源WAF的威力,最好的方式就是亲手从零搭建一套环境,看着它如何拦截攻击。这次,我就以经典的Ubuntu 16.04 LTS为舞台,带大家走一遍完整的实战流程:从理解WAF是什么、能干什么开始,到部署ModSecurity这个核心引擎,接着搭建LAMP环境作为“靶场”的土壤,然后部署DVWA这个著名的漏洞靶机,最后用真实的攻击去测试WAF的防御效果,并部署强大的OWASP核心规则集。整个过程就像组装一台精密的仪器,每一步都环环相扣。无论你是想深入理解WAF原理的安全工程师,还是希望为自己项目增加一道防线的开发者,这套实操指南都能让你获得从理论到实战的完整认知。我们不止步于“安装成功”,更要追求“理解透彻”和“用得明白”。
2. WAF核心概念与功能深度解析
在动手之前,我们必须先搞清楚,我们到底在部署一个什么东西。WAF,全称Web Application Firewall,翻译过来是Web应用防火墙。但它和传统的网络防火墙(比如iptables)有本质区别。你可以把网络防火墙想象成小区的保安,他只管进出的人是不是本小区的(基于IP和端口),而WAF则是你家门口的智能门锁,它会仔细检查每一个想进来的人手里拿的包裹(HTTP/HTTPS请求),看看里面是不是藏了刀(SQL注入)、毒药(XSS脚本)或者伪造的钥匙(越权访问)。
2.1 WAF的三大核心工作模式
理解工作模式,关系到后续配置和问题排查:
- 反向代理模式:这是最常见的方式。WAF作为一个独立的服务,部署在你的Web服务器(如Apache/Nginx)之前。所有外部流量先到达WAF,经过检测和清洗后,再由WAF转发给后端的真实Web服务器。这种模式对后端服务器透明,部署灵活,但会引入单点故障和额外的网络延迟。我们即将部署的ModSecurity与Apache结合,本质上就是这种模式。
- 透明桥接模式:WAF像一块“网卡”一样串联在网络中,物理上不改变网络拓扑,逻辑上也不改变IP地址。流量流经它时被实时检测。这种模式部署复杂,但对网络影响最小,常用于已有的、不便改动架构的生产环境。
- 主机插件模式:将WAF作为一个模块或插件,直接安装在Web服务器软件内部。比如ModSecurity for Apache就是典型的插件模式。它深度集成,性能损耗相对较小,配置管理也更直接,但和Web服务器版本绑定紧密。
2.2 ModSecurity:规则引擎与检测逻辑
我们选择的ModSecurity,是一个开源的、跨平台的WAF引擎。它本身不提供具体的防御规则,而是一个强大的“规则解释和执行平台”。它的核心工作流程可以概括为“五步检测法”:
- 数据采集:完整地收集HTTP请求的所有部分,包括请求行、请求头、请求体(即使是
multipart/form-data格式的文件上传)、以及后端的响应信息。 - 数据解析与规范化:对采集到的原始数据进行解析,比如对URL进行解码,将POST正文中的参数解析成键值对。这一步至关重要,因为攻击者经常使用编码、混淆来绕过简单的字符串匹配。
- 规则匹配:将解析后的数据,与加载的规则集(Rule Set)进行逐条比对。每条规则本质上是一个“条件-动作”语句。例如:“如果请求参数中包含
<script>标签,并且该请求的目标是登录页面,那么就触发拦截动作”。 - 动作执行:当规则条件被满足时,执行相应的动作。动作可以是:
- 阻断:直接中断连接,返回403或自定义错误页面。
- 记录:将此次事件(包括请求详情、触发的规则ID)记录到审计日志(Audit Log)中,用于后续分析。
- 通过:不采取行动,继续处理。
- 重定向:将请求重定向到另一个URL。
- 日志与审计:无论是否阻断,重要的交易信息和安全事件都会被记录。这是事后溯源、调整规则、分析攻击趋势的黄金数据。
注意:规则的质量直接决定了WAF的防御能力和误报率。一个过于宽松的规则集形同虚设,而一个过于严格的规则集可能会把正常用户的行为也拦截掉。因此,WAF的调优是一个持续的过程。
3. 基础环境准备:Ubuntu 16.04系统与LAMP栈部署
我们选择Ubuntu 16.04 LTS作为基础,主要是因为其长期支持版本带来的稳定性,以及网上丰富的教程和兼容的软件包。虽然它已结束标准支持,但在可控的实验环境中完全可用。
3.1 系统初始化与网络配置
首先,确保你的系统是最新状态。通过SSH连接到你的Ubuntu服务器,执行以下命令:
sudo apt-get update sudo apt-get upgrade -y如果是在本地虚拟机(如VMware或VirtualBox)中安装,确保网络适配器设置为“桥接模式”或“NAT模式”,这样虚拟机才能获得IP地址并与宿主机通信。使用ip addr或ifconfig命令查看获取到的IP地址。
为了方便后续操作,建议安装一些常用工具:
sudo apt-get install -y vim curl wget net-tools3.2 LAMP环境详细部署步骤
LAMP是Linux, Apache, MySQL, PHP的缩写,我们将一步步安装。
步骤一:安装Apache2 Web服务器
sudo apt-get install -y apache2安装完成后,启动Apache并设置开机自启:
sudo systemctl start apache2 sudo systemctl enable apache2此时,在浏览器访问你的服务器IP(如http://192.168.1.100),应该能看到Apache的默认欢迎页面。这说明Web服务基础已经就绪。
步骤二:安装MySQL数据库服务
我们安装MySQL 5.7,这是与Ubuntu 16.04兼容的稳定版本。
sudo apt-get install -y mysql-server mysql-client安装过程中会提示你设置MySQL的root用户密码,请务必设置一个强密码并牢记。安装完成后,运行一个简单的安全脚本,移除一些不安全的默认设置:
sudo mysql_secure_installation这个脚本会依次询问你是否设置验证密码插件、修改root密码、移除匿名用户、禁止root远程登录、删除测试数据库等。对于实验环境,你可以根据提示选择,但生产环境务必全部选择‘Y’。
步骤三:安装PHP及其必要扩展
DVWA需要PHP 5.3以上版本,我们安装PHP 7.0(Ubuntu 16.04默认仓库提供)。
sudo apt-get install -y php7.0 libapache2-mod-php7.0 php7.0-mysql php7.0-gd php7.0-curl php7.0-mbstring php7.0-xmlphp7.0-mysql: 用于PHP连接MySQL数据库。php7.0-gd: 用于图形处理,某些功能可能需要。php7.0-curl,php7.0-mbstring,php7.0-xml: DVWA和一些PHP应用常用的扩展。
安装后,需要重启Apache来加载PHP模块:
sudo systemctl restart apache2创建一个测试PHP文件,验证PHP是否工作正常:
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php然后访问http://你的服务器IP/info.php,应该能看到详细的PHP配置信息页面。确认后,务必删除这个测试文件,因为它会暴露服务器敏感信息。
sudo rm /var/www/html/info.php4. ModSecurity 3.0 的编译、安装与核心配置
ModSecurity有两个主要版本:2.x和3.x。2.x版本作为Apache模块(mod_security2)存在已久。3.x版本进行了重构,核心是一个独立的库(libmodsecurity),然后通过不同的连接器(如mod_security3for Apache)与Web服务器交互。我们选择更现代、性能更好的ModSecurity 3。
4.1 安装编译依赖与环境准备
编译安装需要一系列开发工具和库。首先安装基础编译环境:
sudo apt-get install -y build-essential autoconf automake libtool pkg-config然后安装ModSecurity 3核心和Apache连接器所依赖的特定库:
sudo apt-get install -y libxml2-dev libcurl4-openssl-dev liblua5.3-dev libyajl-dev libpcre3-dev libgeoip-dev libmaxminddb-dev ssdeep libfuzzy-devlibyajl-dev: 用于JSON解析,现代WAF必备。libpcre3-dev: Perl兼容正则表达式库,规则匹配的核心。libgeoip-dev: 地理IP定位支持(可选,但建议安装)。
4.2 编译安装ModSecurity 3核心库(libmodsecurity)
我们不直接从仓库安装,而是从GitHub拉取最新稳定代码编译,以获得更好的控制权和可能的性能优化。
- 下载源代码:
cd /usr/src sudo git clone --depth 1 -b v3/master https://github.com/SpiderLabs/ModSecurity cd ModSecurity - 初始化子模块并编译:
sudo git submodule init sudo git submodule update sudo ./build.sh sudo ./configureconfigure脚本会检查所有依赖。如果报错缺少某个库,请根据提示安装对应的-dev包。 - 编译并安装:
默认安装路径是sudo make sudo make install/usr/local/modsecurity/。核心库文件(libmodsecurity.so)会被安装到系统库目录。
4.3 编译安装Apache连接器(mod_security3)
ModSecurity核心库需要连接器才能与Apache对话。
- 下载Apache连接器代码:
cd /usr/src sudo git clone https://github.com/SpiderLabs/ModSecurity-apache cd ModSecurity-apache - 编译连接器模块: 需要指定
libmodsecurity的路径和Apache的扩展工具apxs2的位置。sudo /usr/bin/apxs2 -I /usr/local/modsecurity/include/ -c -i -a mod_security3.c-I: 指定libmodsecurity头文件路径。-c: 编译。-i: 安装(将编译好的模块mod_security3.so复制到Apache模块目录,通常是/usr/lib/apache2/modules/)。-a: 自动在Apache的mods-enabled目录中创建启用该模块的链接。
如果一切顺利,你会在/etc/apache2/mods-enabled/目录下看到一个security3.conf(或security3.load)文件,它包含了加载mod_security3.so的指令。
4.4 配置ModSecurity并集成到Apache
安装完成后,需要进行关键配置。
- 创建ModSecurity主配置文件:
sudo mkdir -p /etc/modsecurity sudo cp /usr/src/ModSecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf sudo cp /usr/src/ModSecurity/unicode.mapping /etc/modsecurity/ - 修改主配置文件: 用编辑器打开
/etc/modsecurity/modsecurity.conf,有几个关键参数需要调整:sudo vim /etc/modsecurity/modsecurity.conf- 找到
SecRuleEngine指令,默认是DetectionOnly(只检测不拦截)。为了测试防御效果,将其改为On。SecRuleEngine On - 找到
SecAuditEngine指令,确保它是RelevantOnly或On,以启用审计日志。SecAuditEngine RelevantOnly - 找到
SecAuditLog指令,设置审计日志的路径。SecAuditLog /var/log/apache2/modsec_audit.log - 找到
SecDebugLog指令,设置调试日志路径(调试时可打开,生产环境建议关闭)。SecDebugLog /var/log/apache2/modsec_debug.log SecDebugLogLevel 0 # 0为关闭,最高为9
- 找到
- 在Apache站点配置中启用ModSecurity: 我们需要在Apache的配置中告诉它,对哪个站点的请求应用ModSecurity规则。编辑你的站点配置文件(例如默认站点
/etc/apache2/sites-available/000-default.conf),在<VirtualHost>段内添加:<IfModule security3_module> SecRuleEngine On SecAuditEngine RelevantOnly SecAuditLog /var/log/apache2/modsec_audit.log IncludeOptional /etc/modsecurity/*.conf # 后续加载OWASP规则集的路径也在这里指定 IncludeOptional /etc/modsecurity/rules/*.conf </IfModule> - 测试配置并重启Apache:
检查Apache错误日志和ModSecurity审计日志,确认没有报错:sudo apachectl -t # 测试配置文件语法 sudo systemctl restart apache2sudo tail -f /var/log/apache2/error.log sudo tail -f /var/log/apache2/modsec_audit.log
5. 部署DVWA靶机用于攻击测试
有了WAF,我们还需要一个“靶子”来测试其效果。DVWA(Damn Vulnerable Web Application)是一个故意设计成充满漏洞的PHP/MySQL应用,完美契合我们的需求。
5.1 下载与部署DVWA
- 下载DVWA: 可以从GitHub直接克隆最新版本,或者下载稳定版ZIP包。这里使用Git:
cd /var/www/html sudo git clone https://github.com/digininja/DVWA.git sudo chown -R www-data:www-data DVWA/ # 将文件所有权改为Apache运行用户 - 配置DVWA数据库: 首先,以root身份登录MySQL,为DVWA创建一个数据库和用户:
在MySQL提示符下执行:sudo mysql -u root -p
请务必将CREATE DATABASE dvwa; CREATE USER 'dvwa_user'@'localhost' IDENTIFIED BY 'YourStrongPassword123!'; GRANT ALL PRIVILEGES ON dvwa.* TO 'dvwa_user'@'localhost'; FLUSH PRIVILEGES; EXIT;'YourStrongPassword123!'替换成一个强密码。 - 配置DVWA连接文件: DVWA提供了一个配置模板,我们需要复制并修改它:
找到以下关键配置项并进行修改:cd /var/www/html/DVWA/config sudo cp config.inc.php.dist config.inc.php sudo vim config.inc.php
另外,为了允许DVWA运行,需要将安全级别设置为$_DVWA[ 'db_server' ] = '127.0.0.1'; $_DVWA[ 'db_database' ] = 'dvwa'; $_DVWA[ 'db_user' ] = 'dvwa_user'; $_DVWA[ 'db_password' ] = 'YourStrongPassword123!'; // 与MySQL中设置的密码一致low(仅用于测试环境!):$_DVWA[ 'default_security_level' ] = 'low'; - 运行DVWA安装脚本: 在浏览器中访问
http://你的服务器IP/DVWA/setup.php。 点击页面底部的“Create / Reset Database”按钮。DVWA将自动创建所需的数据表。如果一切顺利,你会看到绿色的成功提示。重要安全警告:DVWA的默认登录凭证是
admin/password。在实验完成后,或任何有外部网络访问的环境中,必须立即修改默认密码或直接删除DVWA应用,因为它极其危险。
5.2 配置Apache以适配DVWA
DVWA的某些功能(如文件包含漏洞)可能需要调整PHP配置。编辑PHP的配置文件:
sudo vim /etc/php/7.0/apache2/php.ini找到并修改以下行(如果前面有分号;注释,需要去掉):
allow_url_include = On修改后重启Apache:
sudo systemctl restart apache2再次强调:
allow_url_include = On是一个极不安全的设置,仅在DVWA这样的封闭测试环境中使用。在任何生产服务器上都必须保持为Off。
6. 初试锋芒:手动测试WAF基础防御
在加载强大的OWASP规则集之前,我们先利用ModSecurity自带的几条基础规则,来直观感受一下WAF是如何工作的。
6.1 启用ModSecurity基础规则集
ModSecurity源码中带有一个简单的示例规则集,我们先启用它。
sudo cp /usr/src/ModSecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf # 我们之前已经复制过,这里确保SecRuleEngine是On然后,创建一个基础的规则文件:
sudo vim /etc/modsecurity/rules/basic_rules.conf添加以下几条非常基础的规则:
# 规则1:检测简单的SQL注入尝试(单引号) SecRule ARGS "@detectSQLi" "id:1001,phase:2,deny,status:403,msg:'SQL Injection Attack Detected'" # 规则2:检测简单的XSS尝试(<script>标签) SecRule ARGS|REQUEST_HEADERS "@detectXSS" "id:1002,phase:2,deny,status:403,msg:'XSS Attack Detected'" # 规则3:阻止访问常见的敏感文件(如.git目录、备份文件) SecRule REQUEST_FILENAME “\.(git|bak|old|sql)$” “id:1003,phase:1,deny,status:404,msg:‘Sensitive file access attempt’”在Apache配置中引入这个规则文件(如果之前没加):
IncludeOptional /etc/modsecurity/rules/*.conf重启Apache使规则生效。
6.2 发起测试攻击并观察拦截
- SQL注入测试: 在浏览器中访问DVWA的SQL注入页面 (
http://你的IP/DVWA/vulnerabilities/sqli/),在输入框中尝试输入一个经典的注入载荷:' OR '1'='1。- 无WAF时:提交后,页面可能会显示额外的用户信息,证明注入成功。
- 有WAF时:提交后,你应该会立即收到一个403 Forbidden错误页面。同时,查看ModSecurity的审计日志:
你会看到一条详细的日志记录,其中包含触发的规则ID(1001)、攻击载荷、以及拦截动作。sudo tail -f /var/log/apache2/modsec_audit.log
- XSS测试: 访问DVWA的XSS反射型漏洞页面 (
http://你的IP/DVWA/vulnerabilities/xss_r/),在输入框中输入:<script>alert('xss')</script>。- 无WAF时:提交后,浏览器会弹出一个警告框。
- 有WAF时:提交后,同样会被拦截并返回403。审计日志中会记录规则ID 1002。
通过这个简单测试,你可以清晰地看到,WAF在HTTP请求到达脆弱的DVWA应用之前,就根据规则识别出了恶意特征并将其阻断。攻击载荷根本没有机会接触到后端PHP代码。
7. 部署OWASP核心规则集(CRS):获得企业级防护
手动写的几条规则远远不够。OWASP ModSecurity核心规则集是一个由安全社区维护的、包含数百条针对各种已知攻击模式(SQLi, XSS, RCE, LFI等)的规则集合。它是生产环境WAF的基石。
7.1 下载与部署OWASP CRS
- 下载最新版CRS:
cd /usr/src sudo git clone https://github.com/coreruleset/coreruleset.git - 将规则文件复制到ModSecurity配置目录:
sudo mkdir -p /etc/modsecurity/crs sudo cp -r /usr/src/coreruleset/rules/* /etc/modsecurity/crs/ sudo cp /usr/src/coreruleset/crs-setup.conf.example /etc/modsecurity/crs/crs-setup.conf - 配置CRS: 编辑
crs-setup.conf,这是CRS的主配置文件。我们主要关注几个地方:sudo vim /etc/modsecurity/crs/crs-setup.conf- 设置规则检测模式:找到
SecDefaultAction,确保其动作是deny(拦截)。通常CRS默认是phase:2,log,auditlog,pass(仅记录),我们需要改为拦截。SecDefaultAction “phase:2,log,auditlog,deny,status:403” - 设置异常评分阈值:CRS使用“异常评分”机制。每条规则匹配会累加分数。当总分数超过阈值时,请求才会被阻断。找到并调整这些阈值(通常位于文件末尾的
# — [[ Anomaly Scoring Mode ]] —部分):
这里# 设置拦截阈值 SecAction \ “id:900110,\ phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.inbound_anomaly_score_threshold=5,\ setvar:tx.outbound_anomaly_score_threshold=4”inbound指入站请求(攻击请求)的阈值,outbound指出站响应(数据泄露)的阈值。值越小越敏感,但误报可能越高。可以从默认值开始测试。 - 启用必要的规则文件:CRS的规则按类别放在不同文件中。我们需要在Apache配置中按需引入。一个常见的做法是创建一个主配置文件来包含它们。
- 设置规则检测模式:找到
7.2 在Apache中集成CRS
在/etc/modsecurity/rules/目录下创建一个主规则文件,例如main.conf:
sudo vim /etc/modsecurity/rules/main.conf内容如下:
# 包含ModSecurity主配置 Include /etc/modsecurity/modsecurity.conf # 包含CRS配置文件 Include /etc/modsecurity/crs/crs-setup.conf # 包含CRS规则文件(按需启用) Include /etc/modsecurity/crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf Include /etc/modsecurity/crs/rules/REQUEST-901-INITIALIZATION.conf Include /etc/modsecurity/crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf Include /etc/modsecurity/crs/rules/REQUEST-910-IP-REPUTATION.conf Include /etc/modsecurity/crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf Include /etc/modsecurity/crs/rules/REQUEST-912-DOS-PROTECTION.conf Include /etc/modcurity/crs/rules/REQUEST-913-SCANNER-DETECTION.conf Include /etc/modsecurity/crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf # 包含SQLi, XSS等 Include /etc/modsecurity/crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf Include /etc/modsecurity/crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf Include /etc/modsecurity/crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf Include /etc/modsecurity/crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf Include /etc/modsecurity/crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf Include /etc/modsecurity/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf Include /etc/modsecurity/crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf Include /etc/modsecurity/crs/rules/RESPONSE-950-DATA-LEAKAGES.conf Include /etc/modsecurity/crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf Include /etc/modsecurity/crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf Include /etc/modsecurity/crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf Include /etc/modsecurity/crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf Include /etc/modsecurity/crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf Include /etc/modsecurity/crs/rules/RESPONSE-980-CORRELATION.conf Include /etc/modsecurity/crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf然后,修改Apache的站点配置,将之前包含单个规则文件的指令,改为包含这个main.conf:
IncludeOptional /etc/modsecurity/rules/main.conf最后,重启Apache服务:
sudo systemctl restart apache28. 全面攻防测试与WAF效果验证
现在,我们拥有了一个搭载了企业级规则集(OWASP CRS)的WAF。让我们对DVWA发起更全面、更真实的攻击,来检验这套防御体系的威力。
8.1 高级攻击测试用例
在DVWA的安全级别设置为low的情况下,尝试以下攻击:
- 复杂SQL注入:
- 攻击载荷:在SQL注入页面输入:
1' UNION SELECT user, password FROM users# - 预期结果(无WAF):可能会显示数据库中的用户名和密码哈希。
- WAF拦截:CRS的规则
942100(检测SQL注释符)和942110(检测SQL UNION查询)等会被触发。请求将被阻断,返回403。查看审计日志,可以看到触发的规则ID和累计的异常分数。
- 攻击载荷:在SQL注入页面输入:
- 存储型XSS:
- 攻击载荷:在XSS存储型页面,名字输入框输入:
<img src=x onerror=alert(document.cookie)> - 预期结果(无WAF):该脚本会被存入数据库,之后任何用户查看该页面时,其Cookie信息都会被弹出。
- WAF拦截:CRS的规则
941100(检测XSS via libinjection)和941110(检测XSS过滤器)会立即识别出onerror事件和可疑的HTML属性,在请求提交阶段就进行阻断。
- 攻击载荷:在XSS存储型页面,名字输入框输入:
- 命令注入:
- 攻击载荷:在命令注入页面,输入:
127.0.0.1; cat /etc/passwd - 预期结果(无WAF):服务器会执行
cat /etc/passwd命令并返回结果。 - WAF拦截:CRS的规则
932100(检测Unix命令注入)会检测到分号;和系统命令cat,从而阻断请求。
- 攻击载荷:在命令注入页面,输入:
- 文件包含:
- 攻击载荷:在文件包含页面,修改参数为:
../../../../etc/passwd - 预期结果(无WAF):服务器可能会返回
/etc/passwd文件的内容。 - WAF拦截:CRS的规则
930100(检测路径遍历)会检测到过多的../序列,触发拦截。
- 攻击载荷:在文件包含页面,修改参数为:
8.2 分析审计日志与调优规则
攻击测试后,审计日志/var/log/apache2/modsec_audit.log是你的宝藏。它记录了每一次拦截的详细信息。一条典型的日志包含:
- 请求部分:完整的HTTP请求头、参数、Body。
- 响应部分:服务器返回的响应(如果请求被阻断,可能没有)。
- 审计数据部分:这是核心,包含了触发的规则列表、每条规则的ID和消息、以及本次请求的异常分数(anomaly score)。
例如,你可能会看到:
Message: Warning. detected SQLi using libinjection. [file “/etc/modsecurity/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf”] [line “108”] [id “942100”] [msg “SQL Injection Attack Detected via libinjection”] [data “Matched Data: s&1 found within ARGS:id: 1' UNION SELECT user, password FROM users#”] [severity “CRITICAL”] [ver “OWASP_CRS/3.3.0”] [tag “application-multi”] [tag “language-multi”] [tag “platform-multi”] [tag “attack-sqli”] [tag “paranoia-level/1”] [tag “OWASP_CRS”] [tag “capec/1000/152/248/66”] [tag “PCI/6.5.2”] Message: Warning. Operator GE matched 5 at TX:anomaly_score. [file “/etc/modsecurity/crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf”] [line “91”] [id “949110”] [msg “Inbound Anomaly Score Exceeded (Total Score: 15)”] [severity “CRITICAL”] [ver “OWASP_CRS/3.3.0”] [tag “application-multi”] [tag “language-multi”] [tag “platform-multi”] [tag “attack-generic”]第一条日志是具体的SQL注入规则匹配,第二条日志显示异常总分超过了阈值(15 > 5),因此请求被阻断。
调优经验:在实际生产环境中,初期可能会遇到误报(False Positive),即正常业务请求被WAF拦截。这时,你需要:
- 分析日志:定位是哪个规则ID拦截了正常请求。
- 创建排除规则:在
REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf文件中,为特定的URL路径或参数添加规则,使其跳过某些检查。例如,如果你的某个API接口/api/upload需要接收包含特殊字符的JSON,你可以添加:
这条规则表示,对于以SecRule REQUEST_URI “@beginsWith /api/upload” \ “id:10000,\ phase:1,\ pass,\ nolog,\ ctl:ruleRemoveTargetById=942100;ARGS:json_data”/api/upload开头的请求,在规则ID为942100的检查中,排除json_data这个参数。 - 调整阈值:如果误报较多,可以适当提高
tx.inbound_anomaly_score_threshold的值(比如从5调到10),让WAF更“宽容”一些。但这会降低安全性,需谨慎。
9. 常见问题、故障排查与性能考量
在部署和测试过程中,你几乎一定会遇到一些问题。这里记录一些典型的坑和解决方法。
9.1 安装与编译问题
- 问题:编译ModSecurity时
configure失败,提示缺少依赖。- 排查:仔细阅读错误信息,通常会明确指出是哪个库(如
libyajl)没找到。 - 解决:使用
apt-cache search查找对应的-dev包并安装。例如:sudo apt-get install libyajl-dev。
- 排查:仔细阅读错误信息,通常会明确指出是哪个库(如
- 问题:Apache启动失败,错误日志显示
mod_security3.so未找到或加载失败。- 排查:检查
/etc/apache2/mods-enabled/下是否有security3.load文件,以及其指向的.so文件路径是否正确。使用ls -la /usr/lib/apache2/modules/mod_security3.so确认文件存在。 - 解决:可能是连接器编译安装失败。重新执行
apxs2编译命令,并确保libmodsecurity的安装路径正确。
- 排查:检查
9.2 规则与拦截问题
- 问题:WAF似乎没有生效,攻击请求没有被拦截。
- 排查步骤:
- 确认
SecRuleEngine是否为On。 - 检查Apache错误日志
error.log,看是否有ModSecurity相关的加载错误。 - 检查审计日志
modsec_audit.log是否有新条目生成。如果没有,可能是日志路径配置错误或权限问题。 - 使用
curl或浏览器插件发送一个简单的测试载荷:curl ‘http://your-ip/DVWA/vulnerabilities/sqli/?id=1%27‘,观察日志。
- 确认
- 解决:逐项检查配置文件语法和路径。确保Apache配置中正确包含了规则文件。
- 排查步骤:
- 问题:正常业务请求被WAF拦截(误报)。
- 排查:这是WAF部署后最常见的问题。第一时间查看
modsec_audit.log,找到拦截该请求的日志条目,重点关注触发的规则ID(id)和匹配的数据(Matched Data)。 - 解决:
- 短期:根据规则ID,在
REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf中添加针对该URL或参数的排除规则。 - 长期:分析误报模式。如果是某个特定功能(如富文本编辑器)导致大量XSS误报,可以考虑对该功能的上传/提交接口单独放宽策略,或者采用更精准的规则集(如调整CRS的
paranoia level,级别越高检测越严格,误报也可能越高)。
- 短期:根据规则ID,在
- 排查:这是WAF部署后最常见的问题。第一时间查看
9.3 性能考量与优化建议
WAF不是免费的,它会消耗CPU和内存资源,增加请求延迟。在生产环境部署前,务必进行压力测试。
- 性能影响点:
- 规则数量与复杂度:规则越多、正则表达式越复杂,匹配耗时越长。
- 请求体解析:特别是解析大型文件上传(
multipart/form-data)或JSON/XML时,开销较大。 - 审计日志记录:将完整的请求/响应写入磁盘是I/O密集型操作。
- 优化建议:
- 精简规则:只启用你需要的规则集。例如,如果你的应用不是PHP,可以禁用
REQUEST-933-APPLICATION-ATTACK-PHP.conf。 - 调整审计日志:将
SecAuditLogParts设置为只记录必要部分(如ABIEFHZ),而不是完整的请求响应(ABIEFHZ)。在生产环境,可以考虑将审计日志写入内存文件系统或使用异步日志。 - 使用检测模式:上线初期,将
SecRuleEngine设置为DetectionOnly,观察一段时间,分析日志中的误报和漏报,调整好规则后再切换到On。 - 硬件与架构:对于高流量网站,考虑将WAF部署在独立的、性能更强的反向代理服务器上,或者使用商业WAF的云服务,它们通常有硬件加速和更优化的引擎。
- 精简规则:只启用你需要的规则集。例如,如果你的应用不是PHP,可以禁用
从在Ubuntu上敲下第一条apt-get命令,到看着OWASP CRS成功拦截下一个个精心构造的攻击载荷,这个完整的搭建与测试过程,其价值远超过仅仅知道几个概念。你亲手验证了WAF作为安全边界的关键作用:它像一道滤网,在恶意流量触及脆弱应用之前将其过滤。更重要的是,你接触到了WAF运维的核心——规则管理。如何平衡安全与误报,如何根据业务特点调整策略,这些经验才是从“会用”到“精通”的关键。这套环境本身也是一个绝佳的学习沙盒,你可以尝试修改规则、模拟更复杂的绕过攻击、甚至学习编写自己的ModSecurity规则,从而更深层次地理解Web安全的攻防逻辑。