6

最近,一位黑客试图使用睡眠注入来减慢我的网站速度。尽管我们正在使用预防措施,例如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. 使用一些自定义功能从输入中删除单词睡眠

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

4

4 回答 4

21

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

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

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

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

$id = (int)$_GET['id'];
于 2013-01-27T07:30:15.277 回答
11

防止 SQL 注入的最佳方法是使用当前技术。MySQLmysql_系列函数已被弃用,并将在未来的修订版中从 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
    }
    

发生的情况是您传递给的 SQL 语句prepare由数据库服务器解析和编译。通过指定参数(a?或命名参数,如:name),您可以告诉数据库引擎您要过滤的内容。然后,当您调用execute准备好的语句时,将与您指定的参数值相结合。

这里重要的是参数值与编译语句组合在一起,而不是 SQL 字符串。SQL 注入的工作原理是在创建要发送到数据库的 SQL 时诱使脚本包含恶意字符串。因此,通过将实际 SQL 与参数分开发送,您可以限制以您不想要的东西结束的风险。您在使用准备好的语句时发送的任何参数都将被视为字符串(尽管数据库引擎可能会进行一些优化,因此参数也可能最终以数字形式结束)。

于 2013-01-27T07:28:47.057 回答
2

这是一个错误的问题。

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

这个问题已经有很多答案了

于 2013-01-27T07:30:55.103 回答
0

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

于 2013-01-27T07:30:22.563 回答