如何防止MySQL睡眠注射?

时间:2013-01-27 07:23:26

标签: php mysql sql-injection

最近有一名黑客试图使用睡眠注射减慢我的网站速度。虽然我们正在使用mysql_real_escape_string()等预防措施来覆盖大多数易受攻击的输入。我们通过查询字符串传递产品的id,并将命令设为:

$id = mysql_real_escape_string($_REQUEST['id']);
$qry = "Select * from products where id = ".$id;

但是黑客试图提供输入

?id=3 and sleep(4)

并且查询变为

Select * from products where id = 3 and sleep(4);

虽然有一些可能的解决方案,如

  1. 检查产品ID是否为数字
  2. 使用某些自定义功能
  3. 从输入中删除单词sleep

    还有其他方法可以阻止这种情况吗?什么是预防睡眠注射的最佳方法?

4 个答案:

答案 0 :(得分:20)

你没有正确逃脱。 mysql_real_escape_string用于正确转义SQL string 语法,但您只是将值嵌入为裸值,而不是SQL字符串。你需要:

$qry = "SELECT * FROM products WHERE id = '$id'";

请注意查询中id周围的引号。

如果id是数字,则转换为数字会更明智:

$id = (int)$_GET['id'];

答案 1 :(得分:10)

防止SQL注入的最佳方法是使用当前技术。不推荐使用MySQL mysql_系列函数,将在以后的版本中从PHP中删除。

您应该使用MySQLi或PDO的预准备语句。

这些技术使用预准备语句和参数化查询。 SQL语句由数据库服务器与任何参数分开解析。攻击者无法注入恶意SQL。

你基本上有两个选择来实现这个目标:

  1. MySQLi

    $stmt = $dbConnection->prepare('SELECT * FROM table WHERE name = ?');
    $stmt->bind_param('s', $name);
    $stmt->execute();
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        // do something with $row
    }
    
  2. PDO

    $stmt = $pdo->prepare('SELECT * FROM table WHERE name = :name');
    $stmt->execute(array(':name' => $name));
    foreach ($stmt as $row) {
        // do something with $row
    }
    
  3. 您传递给prepare的SQL语句会被数据库服务器解析和编译。通过指定参数(?或命名参数,如:name),您可以告诉数据库引擎要过滤的内容。然后,当您调用execute时,预准备语句将与您指定的参数值组合。

    这里重要的是参数值与编译语句结合,而不是SQL字符串。 SQL注入通过在创建SQL以发送到数据库时欺骗脚本来包含恶意字符串。因此,通过从参数中单独发送实际SQL,可以限制结束您不想要的内容的风险。使用预准备语句时发送的任何参数都将被视为字符串(尽管数据库引擎可能会进行一些优化,因此参数最终也可能作为数字)。

答案 2 :(得分:2)

这是一个错误的问题。

如何防止mysql注入?”必须如此。睡觉或不睡觉 - 没关系。

此问题已经很多的答案

答案 3 :(得分:0)

您应该使用PDO或mysqli将查询转换为“预备语句”。