介绍
ModSecurity是一个免费的Web应用程序防火墙(WAF),与Apache,Nginx和IIS配合使用。 它支持一个灵活的规则引擎来执行简单和复杂的操作,并配备了核心规则集(CRS),它有SQL注入,跨站脚本,特洛伊木马,坏用户代理,会话劫持和许多其他漏洞的规则。 对于Apache,它作为一个附加模块加载,这使得它易于安装和配置。
先决条件
要遵循本教程,您需要:
一个Ubuntu 14.04或Debian 8 Droplet。
使用sudo的特权,您可以通过以下的初始服务器设置教程建立一个标准用户帐户的Ubuntu 14.04或Debian 8 。
一个LAMP,您可以通过下面的教程安装的Ubuntu 14.04或Debian 8 。
第1步 - 安装ModSecurity
在这一步,我们将安装ModSecurity。
首先,更新包索引文件。
sudo apt-get update
然后,安装ModSecurity。
sudo apt-get install libapache2-mod-security2 -y
您可以使用以下命令验证是否已加载ModSecurity模块。
sudo apachectl -M | grep --color security2
如果输出读取security2_module (shared)
,这表明该模块被加载。
ModSecurity的安装包括一个必须重命名的推荐配置文件。
sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
最后,重新加载Apache。
sudo service apache2 reload
对于ModSecurity的新的日志文件将在Apache日志目录中创建/var/log/apache2/modsec_audit.log
。
第2步 - 配置ModSecurity
开箱即用,ModSecurity不做任何事情,因为它需要规则才能工作。 在这一步中,我们将首先启用一些配置指令。
要查找和替换此步骤中的配置指令,我们将使用sed
,一个流编辑器。 您可以阅读sed
教程系列 ,以了解更多有关该工具。
启用基本指令
默认的ModSecurity配置文件设置为DetectionOnly
,它记录按照规则匹配的请求,并不会阻止任何东西。 这可以通过编辑来改变modsecurity.conf
文件和修改SecRuleEngine
指令。 如果您在生产服务器上尝试此操作,请仅在测试所有规则后更改此指令。
sudo sed -i "s/SecRuleEngine DetectionOnly/SecRuleEngine On/" /etc/modsecurity/modsecurity.conf
该SecResponseBodyAccess
指令配置响应主体是否缓冲(即由ModSecurity的读取)。 只有在需要数据泄漏检测和保护时才需要。 因此,保留它将使用Droplet资源,并增加日志文件大小,所以我们将其关闭。
sudo sed -i "s/SecResponseBodyAccess On/SecResponseBodyAccess Off/" /etc/modsecurity/modsecurity.conf
要修改的可选指令
有可能要通过编辑自定义其他指令/etc/modsecurity/modsecurity.conf
。 该SecRequestBodyLimit
和SecRequestBodyNoFilesLimit
指令限制可以发布到Web应用程序的最大数据。
特别是, SecRequestBodyLimit
指令指定的最大POST数据大小。 如果有什么大的客户端发送服务器会回应一个413请求实体过大的错误。 如果您的Web应用程序没有任何文件上传,则此值可以保持原样。 配置文件中指定的预配置值为13107200字节(12.5MB)。 如果你想改变这个值,查找下面一行modsecurity.conf
:
SecRequestBodyLimit 13107200
同样, SecRequestBodyNoFilesLimit
限制POST数据减去上传文件的大小。 该值应设置为尽可能低,以便在有人发送非常大的请求主体时减少对拒绝服务(DoS)攻击的敏感性。 配置文件中的预配置值为131072字节(128KB)。 如果你想改变这个值,查找下面一行modsecurity.conf
:
SecRequestBodyNoFilesLimit 131072
影响服务器性能的指令时SecRequestBodyInMemoryLimit
。 这个指令是很自明的; 它指定应将多少“请求主体”数据(POSTed数据)保存在内存(RAM)中,任何更多的将被放置在硬盘中(就像交换一样)。 因为Droplets使用SSD,这不是很大的问题。 但是,如果您有RAM可用,可以更改。 此伪指令的预配置值为128KB。 如果你想改变这个值,查找下面一行modsecurity.conf
:
SecRequestBodyInMemoryLimit 131072
第3步 - 测试SQL注入
在配置一些规则之前,我们将创建一个易受SQL注入影响的PHP脚本,以测试ModSecurity的保护。
注意:这是一个基本的PHP登录脚本,没有会话处理或表单卫星。 它只是作为一个例子来测试SQL注入和ModSecurity的规则。 它将在教程结束之前删除。
首先,访问MySQL提示符。
mysql -u root -p
在这里,创建一个MySQL数据库称为样品并连接到它。
create database sample;
connect sample;
然后创建一个包含一些凭证表-用户名sammy和密码password。
create table users(username VARCHAR(100),password VARCHAR(100));
insert into users values('sammy','password');
最后,退出MySQL提示符。
quit;
接下来,在Apache的文档根目录中创建登录脚本。
sudo nano /var/www/html/login.php
将以下PHP脚本粘贴到文件中。 请务必将以下脚本中的MySQL密码更改为之前设置的密码,以便脚本可以连接到数据库:
<html>
<body>
<?php
if(isset($_POST['login']))
{
$username = $_POST['username'];
$password = $_POST['password'];
$con = mysqli_connect('localhost','root','your_mysql_password','sample');
$result = mysqli_query($con, "SELECT * FROM `users` WHERE username='$username' AND password='$password'");
if(mysqli_num_rows($result) == 0)
echo 'Invalid username or password';
else
echo '<h1>Logged in</h1><p>This is text that should only be displayed when logged in with valid credentials.</p>';
}
else
{
?>
<form action="" method="post">
Username: <input type="text" name="username"/><br />
Password: <input type="password" name="password"/><br />
<input type="submit" name="login" value="Login"/>
</form>
<?php
}
?>
</body>
</html>
此脚本将显示登录表单。 打开浏览器,浏览到http:// your_server_ip /login.php
看到它。 如果你输入正确的对的凭据,如sammy在密码字段用户名字段和密码,您将看到消息这是有效凭据登录时,只有被显示的文本 。 如果您导航回到登录屏幕,并使用不正确的凭据,你会看到消息无效的用户名或密码 。
下一个工作是尝试SQL注入绕过登录页面。 为用户名字段输入以下内容。
' or true --
注意,应该有后一个空间--
此注射工作。 将密码字段留空,然后点击登录按钮。 该脚本显示用于已验证用户的消息! 在下一步中,我们将阻止这一点。
第4步 - 设置规则
在这一步中,我们将设置一些ModSecurity规则。
启用CRS
为了使事情更容易,有很多规则已经与ModSecurity一起安装。 这些被称为CRS(核心规则集),并位于/usr/share/modsecurity-crs
目录。 要加载这些规则,我们需要配置Apache读取.conf
在这些目录中的文件,所以打开security2.conf
文件进行编辑。
sudo nano /etc/apache2/mods-enabled/security2.conf
添加以下两个指令,以红色突出显示,在文件的最后一行前内侧( </IfModule>
)。
IncludeOptional /etc/modsecurity/*.conf
IncludeOptional "/usr/share/modsecurity-crs/*.conf"
IncludeOptional "/usr/share/modsecurity-crs/activated_rules/*.conf"
</IfModule>
保存并关闭文件。
排除目录/域(可选)
有时,如果运行应用程序(如phpMyAdmin),排除特定目录或域名是有意义的,因为ModSecurity将阻止SQL查询。 最好是排除CMS应用程序的管理后端,如WordPress。 如果您在新服务器上关注本教程,则可以跳过此步骤。
要禁用ModSecurity的一个完整的虚拟主机,将里面的下列指令<VirtualHost>[...]</VirtualHost>
块在其虚拟主机文件。
<IfModule security2_module>
SecRuleEngine Off
</IfModule>
忽略了一个特定的目录(例如, /var/www/wp-admin
):
<Directory "/var/www/wp-admin">
<IfModule security2_module>
SecRuleEngine Off
</IfModule>
</Directory>
如果你不希望在一个目录完全禁用的ModSecurity,使用SecRuleRemoveById
指令通过指定的ID删除特定的规则或规则链。
<LocationMatch "/wp-admin/update.php">
<IfModule security2_module>
SecRuleRemoveById 981173
</IfModule>
</LocationMatch>
激活SQL注入规则
接下来,我们将激活SQL注入规则文件。 所需的规则文件应该被符号链接到activated_rules
目录,这是类似Apache的mods-enabled
目录。 更改为activated_rules
目录。
cd /usr/share/modsecurity-crs/activated_rules/
然后创建从一个符号链接modsecurity_crs_41_sql_injection_attacks.conf
文件。
sudo ln -s ../base_rules/modsecurity_crs_41_sql_injection_attacks.conf .
最后,重新加载Apache使规则生效。
sudo service apache2 reload
现在打开我们之前创建的登录页面,并尝试在用户名字段使用相同的SQL注入查询。 因为我们改变了SecRuleEngine
指令, On
第2步中,将显示一个403 Forbidden错误。 (如果SecRuleEngine
留给了DetectionOnly
选项,注入将是成功的,但企图将在被记录modsec_audit.log
文件)。
因为这个PHP登录脚本只是为了测试ModSecurity,你现在应该删除它的测试完成。
sudo rm /var/www/html/login.php
第5步 - 编写自己的规则
在本节中,我们将创建一个规则链,如果在HTML表单中输入通常与垃圾邮件相关联的某些字词,则会阻止该请求。
首先,我们将创建一个示例PHP脚本,它从文本框获取输入并将其显示回用户。 打开一个名为form.php
进行编辑。
sudo nano /var/www/html/form.php
粘贴以下代码:
<html>
<body>
<?php
if(isset($_POST['data']))
echo $_POST['data'];
else
{
?>
<form method="post" action="">
Enter something here:<textarea name="data"></textarea>
<input type="submit"/>
</form>
<?php
}
?>
</body>
</html>
自定义规则可以添加到任何配置文件或放置在ModSecurity目录中。 我们会在我们的规则中被称为一个独立的新文件modsecurity_custom_rules.conf
。
sudo nano /etc/modsecurity/modsecurity_custom_rules.conf
将以下内容粘贴到此文件中。 这两个词我们封锁是blockedword1和blockedword2。
SecRule REQUEST_FILENAME "form.php" "id:'400001',chain,deny,log,msg:'Spam detected'"
SecRule REQUEST_METHOD "POST" chain
SecRule REQUEST_BODY "@rx (?i:(blockedword1|blockedword2))"
对于语法SecRule
是SecRule VARIABLES OPERATOR [ACTIONS]
。 在这里,我们用行动链相匹配的变量REQUEST_FILENAME
与form.php
, REQUEST_METHOD
与POST
和REQUEST_BODY
正则表达式(@rx)
字符串(blockedword1|blockedword2)
在?i:
做一个不区分大小写的匹配。 在所有这三个规则匹配成功,该ACTION
是拒绝和日志与msg "Spam detected."
链动作模拟的逻辑和所有的三个规则相匹配。
保存文件并重新加载Apache。
sudo service apache2 reload
开http:// your_server_ip /form.php
在浏览器中。 如果输入包含blockedword1或blockedword2的文本,您将看到一个403页面。
因为这个PHP表单脚本只是为了测试ModSecurity,你现在应该删除它的测试完成。
sudo rm /var/www/html/form.php
结论
在本教程中,您已经学习了如何安装和配置ModSecurity,并添加自定义规则。 要了解更多信息,你可以检查出官方的ModSecurity文件 。