如何在Debian/Ubuntu上使用Apache设置mod security

来自菜鸟教程
跳转至:导航、​搜索

序幕


Mod security 是一个免费的 Web 应用程序防火墙 (WAF),可与 Apache、Nginx 和 IIS 配合使用。 它支持灵活的规则引擎来执行简单和复杂的操作,并附带一个核心规则集 (CRS),其中包含 SQL 注入、跨站点脚本、特洛伊木马、不良用户代理、会话劫持和许多其他漏洞的规则。 对于 Apache,它是一个附加模块,可以轻松安装和配置。

为了完成本教程,您需要在服务器上安装 LAMP

安装 mod_security


Modsecurity 在 Debian/Ubuntu 存储库中可用:

apt-get install libapache2-modsecurity

验证是否加载了 mod_security 模块。

apachectl -M | grep --color security

您应该会看到一个名为 security2_module (shared) 的模块,它表明该模块已加载。

Modsecurity 的安装包括一个必须重命名的推荐配置文件:

mv /etc/modsecurity/modsecurity.conf{-recommended,}

重新加载 Apache

service apache2 reload

您将在 Apache 日志目录中找到 mod_security 的新日志文件:

root@droplet:~# ls -l /var/log/apache2/modsec_audit.log
-rw-r----- 1 root root 0 Oct 19 08:08 /var/log/apache2/modsec_audit.log

配置 mod_security


开箱即用,modsecurity 不做任何事情,因为它需要规则才能工作。 默认配置文件设置为 DetectionOnly,它根据规则匹配记录请求并且不阻止任何内容。 这可以通过编辑 modsecurity.conf 文件来改变:

nano /etc/modsecurity/modsecurity.conf

找到这条线

SecRuleEngine DetectionOnly

并将其更改为:

SecRuleEngine On

如果您在生产服务器上尝试此操作,请仅在测试所有规则后更改此指令。

另一个要修改的指令是 SecResponseBodyAccess。 这配置响应体是否被缓冲(即 由 modsecurity 读取)。 只有在需要数据泄漏检测和保护时才需要这样做。 因此,将其保留为 On 会耗尽 droplet 资源并增加日志文件的大小。

找到这个

SecResponseBodyAccess On

并将其更改为:

SecResponseBodyAccess Off

现在我们将限制可以发布到您的 Web 应用程序的最大数据量。 两个指令配置这些:

SecRequestBodyLimit
SecRequestBodyNoFilesLimit

SecRequestBodyLimit 指令指定最大 POST 数据大小。 如果客户端发送任何更大的内容,服务器将响应 413 Request Entity Too Large 错误。 如果您的 Web 应用程序没有任何文件上传,则此值可以大大降低。

配置文件中提到的值为

SecRequestBodyLimit 13107200

这是12.5MB。

与此类似的是 SecRequestBodyNoFilesLimit 指令。 唯一的区别是这个指令限制了 POST 数据减去文件上传的大小——这个值应该“尽可能低”。

配置文件中的值为

SecRequestBodyNoFilesLimit 131072

这是128KB。

沿着这些指令还有另一个影响服务器性能的指令:SecRequestBodyInMemoryLimit。 该指令几乎是不言自明的; 它指定了应该将多少“请求主体”数据(POSTed 数据)保存在内存(RAM)中,更多的将被放置在硬盘中(就像 交换 )。 由于液滴使用 SSD,这不是什么大问题。 但是,如果您有空闲的 RAM,这可以设置一个不错的值。

SecRequestBodyInMemoryLimit 131072

这是配置文件中指定的值 (128KB)。

测试 SQL 注入


在继续配置规则之前,我们将创建一个易受 SQL 注入攻击的 PHP 脚本并进行尝试。 请注意,这只是一个基本的 PHP 登录脚本 ,没有会话处理。 请务必在下面的脚本中更改 MySQL 密码,以便它连接到数据库:

/var/www/login.php

<html>
<body>
<?php
    if(isset($_POST['login']))
    {
        $username = $_POST['username'];
        $password = $_POST['password'];
        $con = mysqli_connect('localhost','root','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>A Secret for you....</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>

该脚本将显示一个登录表单。 输入正确的凭据将显示一条消息“A Secret for you”。

我们需要数据库中的凭据。 创建一个 MySQL 数据库和一个表,然后插入用户名和密码。

mysql -u root -p

这将带您进入 mysql> 提示符

create database sample;
connect sample;
create table users(username VARCHAR(100),password VARCHAR(100));
insert into users values('jesin','pwd');
insert into users values('alice','secret');
quit;

打开浏览器,导航到 http://yourwebsite.com/login.php 并输入正确的凭据对。

Username: jesin
Password: pwd

您将看到指示成功登录的消息。 现在回来输入一对错误的凭据 - 您将看到消息 Invalid username or password

我们可以确认脚本工作正常。 接下来的工作是尝试使用 SQL 注入绕过登录页面。 在 用户名 字段中输入以下内容:

' or true -- 

请注意,在 -- 之后应该有一个空格,如果没有该空格,此注入将无法工作。 将 密码 字段留空并点击登录按钮。

瞧! 该脚本显示用于经过身份验证的用户的消息。

设置规则


为了让你的生活更轻松,有很多规则已经与 mod_security 一起安装。 这些称为 CRS(核心规则集),位于

root@droplet:~# ls -l /usr/share/modsecurity-crs/
total 40
drwxr-xr-x 2 root root  4096 Oct 20 09:45 activated_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 base_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 experimental_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 lua
-rw-r--r-- 1 root root 13544 Jul  2  2012 modsecurity_crs_10_setup.conf
drwxr-xr-x 2 root root  4096 Oct 20 09:45 optional_rules
drwxr-xr-x 3 root root  4096 Oct 20 09:45 util

文档可在

root@droplet1:~# ls -l /usr/share/doc/modsecurity-crs/
total 40
-rw-r--r-- 1 root root   469 Jul  2  2012 changelog.Debian.gz
-rw-r--r-- 1 root root 12387 Jun 18  2012 changelog.gz
-rw-r--r-- 1 root root  1297 Jul  2  2012 copyright
drwxr-xr-x 3 root root  4096 Oct 20 09:45 examples
-rw-r--r-- 1 root root  1138 Mar 16  2012 README.Debian
-rw-r--r-- 1 root root  6495 Mar 16  2012 README.gz

要加载这些规则,我们需要告诉 Apache 查看这些目录。 编辑 modsecurity.conf 文件。

nano /etc/apache2/mods-enabled/modsecurity.conf

<IfModule security2_module> </IfModule> 中添加以下指令:

Include "/usr/share/modsecurity-crs/*.conf"
Include "/usr/share/modsecurity-crs/activated_rules/*.conf"

activated_rules 目录类似于 Apache 的 mods-enabled 目录。 规则在目录中可用:

/usr/share/modsecurity-crs/base_rules
/usr/share/modsecurity-crs/optional_rules
/usr/share/modsecurity-crs/experimental_rules

必须在 activated_rules 目录中创建符号链接才能激活它们。 让我们激活 SQL 注入规则。

cd /usr/share/modsecurity-crs/activated_rules/
ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf .

必须重新加载 Apache 才能使规则生效。

service apache2 reload

现在打开我们之前创建的登录页面,并尝试在用户名字段上使用 SQL 注入查询。 如果您将 SecRuleEngine 指令更改为 On,您将看到 403 Forbidden 错误。 如果留给 DetectionOnly 选项,注入将成功,但尝试将记录在 modsec_audit.log 文件中。

编写自己的 mod_security 规则


在本节中,我们将创建一个规则链,如果在 HTML 表单中输入某些“垃圾”字词,则该规则链会阻止请求。 首先,我们将创建一个 PHP 脚本,该脚本从文本框中获取输入并将其显示给用户。

/var/www/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 目录中。 我们将把我们的规则放在一个单独的新文件中。

nano /etc/modsecurity/modsecurity_custom_rules.conf

将以下内容添加到此文件中:

SecRule REQUEST_FILENAME "form.php" "id:'400001',chain,deny,log,msg:'Spam detected'"
SecRule REQUEST_METHOD "POST" chain
SecRule REQUEST_BODY "@rx (?i:(pills|insurance|rolex))"

保存文件并重新加载 Apache。 在浏览器中打开 http://yourwebsite.com/form.php 并输入包含以下任何单词的文本:药丸、保险、劳力士。

您将看到 403 页面和日志条目,或者仅基于 SecRuleEngine 设置的日志条目。 SecRule 的语法是

SecRule VARIABLES OPERATOR [ACTIONS]

在这里,我们使用 chain 操作将变量 REQUEST_FILENAMEform.phpREQUEST_METHODPOST 和 [ X155X]REQUEST_BODY 与正则表达式 (@rx) 字符串 (pills|insurance|rolex)?i: 进行不区分大小写的匹配。 在成功匹配所有这三个规则时,ACTION 将与 denylog 相匹配,并带有消息“检测到垃圾邮件”。 chain 动作模拟逻辑 AND 以匹配所有三个规则。

排除主机和目录


有时排除特定目录或域名是有意义的,如果它正在运行像 phpMyAdmin 这样的应用程序作为 modsecurity 并且会阻止 SQL 查询。 最好排除 WordPress 等 CMS 应用程序的管理后端。

要为完整的 VirtualHost 禁用 modsecurity,请放置以下内容

<IfModule security2_module>
    SecRuleEngine Off
</IfModule>

<VirtualHost> 部分内。

对于特定目录:

<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>

延伸阅读


官方 modsecurity 文档 https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual

提交人:http: [[“%3Ca|//jesin.tk/]] [[“%3C/a|”>杰辛A]]