每天18,000次MySQL注入尝试:停止尝试

时间:2013-08-15 17:59:14

标签: php mysql security

这个问题不是关于防止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返回代码更合适?

编辑:

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

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

4 个答案:

答案 0 :(得分:6)

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

将其配置为识别应用程序的合法请求可能需要相当多的工作。

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

答案 1 :(得分:1)

您可以尝试阻止此流量通过硬件到达您的服务器。大多数进行数据包检测的设备都可以使用。我为此目的使用F5(以及其他)。 F5有一种自己的脚本语言叫做iRules,可以提供很好的控制和定制。

答案 2 :(得分:0)

帖子已被解锁,所以我想我会分享我一直在做的事情,以减少来自同一个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)&gt; 10)由于大多数尝试都包含超过10个字符,因此效果非常好。

答案 3 :(得分:-1)

一个非常好的问题+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地址限制为一定数量的并发连接。许多网站管理员似乎都在鼓吹这是打击僵尸垃圾邮件的好方法,但它看起来似乎不如mod_throttle灵活。

您需要不同版本的mod_limitipconn,具体取决于您正在运行的Apache版本:

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请求,而不是简单地延迟或扩散它们。

祝福内容与垃圾邮件之间不断升级的战斗!