【问题标题】:18,000 MySQL injection attempts per day: Stopping the attempts每天 18,000 次 MySQL 注入尝试:停止尝试
【发布时间】:2013-08-18 00:00:12
【问题描述】:

这个问题不是关于防止 SQL 注入攻击。这个问题在 StackOverflow 上已经回答了很多次,我已经实现了这些技术。这是关于停止尝试

最近,我的网站遭到大量注入攻击。现在,我捕获它们并返回一个静态页面。

我的网址如下所示:

/products/product.php?id=1

这是攻击的样子:

/products/product.php?id=-3000%27%20IN%20BOOLEAN%20MODE%29%20UNION%20ALL%20SELECT%2035%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C%27qopjq%27%7C%7C%27ijiJvkyBhO%27%7C%7C%27qhwnq%27%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35--%20

我确信这不仅仅是错误的链接或粗手指的打字,所以我不想将它们发送到概览页面。我也不想在我的网站上使用任何资源来提供静态页面。

我正在考虑让页面以die() 消失。这种方法有什么问题吗?或者有没有我可以用 PHP 设置的更合适的 HTML 返回码?

编辑:

根据下面的几个 cmets,我查找了如何返回“找不到页面”。 icktoofay 的这个 Stack Overflow answer 建议使用 404,然后使用 die(); - 机器人认为没有页面甚至可能消失,并且没有更多资源用于显示页面未找到消息。

header("HTTP/1.0 404 Not Found");
die();

【问题讨论】:

  • 只使用准备好的语句
  • 返回 403 错误可能有点合适。
  • 服务器前有F5负载均衡器吗?
  • @bksi 如果您阅读第一行,您会注意到问题不是这样的
  • 恕我直言,这个问题与编程无关,它是服务器管理员。

标签: php mysql security


【解决方案1】:

过滤掉可能的注入尝试是mod_security 的用途。

配置它以识别对您的应用的合法请求可能需要做很多工作。

另一种常见的方法是在检测到恶意客户端的 IP 地址时将其阻止。

【讨论】:

  • 谢谢。我会调查的。 IP 地址经常变化,所以这是不可行的。
  • 可行。确定这些请求中普通用户极不可能或不可能触发的特征,然后在他们触发时立即禁止这些 IP。
  • 我收到了匿名反对票。 Downvoter,您能否发表评论告诉我为什么您认为这个答案不好?也许我可以改进它。
【解决方案2】:

您可以尝试通过硬件阻止此流量到达您的服务器。大多数进行数据包检查的设备都可以使用。我为此使用 F5(等等)。 F5 有自己的脚本语言,称为 iRules,可提供出色的控制和自定义功能。

【讨论】:

  • 我使用的是虚拟专用服务器,所以我不认为这是一个选择,但我会看看他们提供什么。
【解决方案3】:

帖子已被解锁,所以我想我会分享我一直在做的事情,以减少来自同一 IP 地址的攻击。我仍然每天得到半打,但他们通常只从每个 IP 地址尝试一次或两次。

注意:为了返回 404 错误消息,所有这些都必须在发送任何 HTML 之前出现。我正在使用 PHP 并将所有错误重定向到错误文件。

<?php
require_once('mysql_database.inc');

// I’m using a database, so mysql_real_escape_string works.
// I don’t use any special characters in my productID, but injection attacks do. This helps trap them.
$productID = htmlspecialchars( (isset($_GET['id']) ? mysql_real_escape_string($_GET['id']) : '55') );

// Product IDs are all numeric, so it’s an invalid request if it isn’t a number.
if ( !is_numeric($productID) ) {
    $url = $_SERVER['REQUEST_URI'];  // Track which page is under attack.
    $ref = $_SERVER['HTTP_REFERER']; // I display the referrer just in case I have a bad link on one of my pages
    $ip  = $_SERVER['REMOTE_ADDR'];  // See if they are comng from the same place each time

    // Strip spaces just in case they typed the URL and have an extra space in it
    $productID=preg_replace('/[\s]+/','',$productID);
    if ( !is_numeric($productID) ) {
        error_log("Still a long string in products.php after replacement: URL is $url and IP is $ip & ref is $ref");
        header("HTTP/1.0 404 Not Found");
        die();
    }
}

我还有很多页面,根据选择的类别,我会在其中显示不同的内容。在这些情况下,我有一系列 if 语句,像这样 if ($cat == 'Speech') { } 没有数据库查找,所以没有 SQL 注入的机会,但我仍然想停止攻击,而不是浪费带宽向机器人显示默认页面。通常类别是一个简短的词,所以我修改上面的 is_numeric 条件来检查字符串长度,例如if ( strlen($cat) > 10 ) 由于大多数尝试都包含超过 10 个字符,因此效果很好。

【讨论】:

    【解决方案4】:

    我提出了一个非常好的问题 +1,答案并不简单。

    PHP 不提供维护不同页面和不同会话的数据的方法,因此您不能通过 IP 地址限制访问,除非您将访问详细信息存储在某处。

    如果您不想为此使用数据库连接,您当然可以使用文件系统。我确定您已经知道如何执行此操作,但您可以在此处查看示例:

    DL's Script Archives
    http://www.digi-dl.com/
    (click on "HomeGrown PHP Scripts", then on "IP/networking", then
    on "View Source" for the "IP Blocker with Time Limit" section)
    

    过去最好的选择是“mod_throttle”。使用它,您可以通过将此指令添加到您的 Apache 配置文件来将每个 IP 地址限制为每五秒一次访问:

    <IfModule mod_throttle.c>
        ThrottlePolicy Request 1 5
    </IfModule>
    

    但是有一些坏消息。 mod_throttle 的作者已经放弃了产品:

    "Snert's Apache modules currently CLOSED to the public 
      until further notice. Questions as to why or requests
      for archives are ignored."
    

    另一个 apache 模块 mod_limitipconn 现在更常用。它不允许您做出任意限制(例如“每十五秒内不超过十个请求”)。您所能做的就是将每个 IP 地址限制为一定数量的并发连接。许多网站管理员似乎都在提倡将其作为对抗 bot 垃圾邮件的好方法,但它似乎不如 mod_throttle 灵活。

    根据您运行的 Apache 版本,您需要不同版本的 mod_limitipconn:

    mod_limitipconn.c - for Apache 1.3
    http://dominia.org/djao/limitipconn.html
    
    mod_limitipconn.c - Apache 2.0 port
    http://dominia.org/djao/limitipconn2.html
    

    最后,如果您的 Apache 服务器托管在 Linux 机器上,那么您可以使用一种无​​需重新编译内核的解决方案。相反,它使用“iptables”防火墙规则。这种方法相当优雅,并且足够灵活,可以施加诸如“一分钟内来自该 IP 的连接不超过三个”之类的限制。以下是它的完成方式:

    Linux Noob forums - SSH Rate Limit per IP
    http://www.linux-noob.com/forums/index.php?showtopic=1829
    

    我意识到这些选项都不是理想的,但它们说明了什么是可能的。也许使用本地数据库最终会是最好的?无论如何,请记住,简单地限制请求速率或限制带宽并不能解决机器人问题。它们可能需要更长的时间,但它们最终会消耗与不放慢速度时一样多的资源。有必要实际拒绝他们的 HTTP 请求,而不是简单地延迟或分散它们。

    祝你在内容和垃圾邮件之间不断升级的战斗中好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-02
      • 1970-01-01
      • 2011-05-03
      相关资源
      最近更新 更多