如何防止MySQL睡眠注射?

dir*_*php 5 php mysql sql-injection

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

$id = mysql_real_escape_string($_REQUEST['id']);
$qry = "Select * from products where id = ".$id;
Run Code Online (Sandbox Code Playgroud)

但是黑客试图提供输入

?id=3 and sleep(4)
Run Code Online (Sandbox Code Playgroud)

和查询成为

Select * from products where id = 3 and sleep(4);
Run Code Online (Sandbox Code Playgroud)

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

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

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

dec*_*eze 20

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

$qry = "SELECT * FROM products WHERE id = '$id'";
Run Code Online (Sandbox Code Playgroud)

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

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

$id = (int)$_GET['id'];
Run Code Online (Sandbox Code Playgroud)

  • +1用于指出正确使用`mysql_real_escape_string`. (3认同)
  • 值得补充的是,"mysql_*"函数已被弃用,不应再使用了. (2认同)

Gor*_*man 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
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. PDO:

    $stmt = $pdo->prepare('SELECT * FROM table WHERE name = :name');
    $stmt->execute(array(':name' => $name));
    foreach ($stmt as $row) {
        // do something with $row
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

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

  • 嘿伙计们,戈登是绝对正确的.如果您认为转义SQL的数据只是一种安全措施,那么您会感到非常惊讶.在您应该转义的上下文中使用它之前,不要转义某些内容的数据.否则,你只是弄乱你的数据!此外,如果您正确构建系统并使用准备好的查询,则永远不可能进行二阶攻击.你可能认为这不是问题......但事实确实如此.即使您没有将其视为安全问题,请记住,字段中的简单引号会在以后搞砸您.也许不是恶意的,但至少打破了. (3认同)