如何保护此代码免受 SQL 注入?有点迷茫

Posted

技术标签:

【中文标题】如何保护此代码免受 SQL 注入?有点迷茫【英文标题】:How can I protect this code from SQL Injection? A bit confused 【发布时间】:2011-02-03 01:23:28 【问题描述】:

我已经阅读了各种资料,但我不确定如何将它们实现到我的代码中。我想知道是否有人可以帮我快速处理它?一旦在我的代码中向我展示了如何做到这一点,我想我就可以把它捡起来!这是来自我在网上找到的 AJAX 自动完成功能,尽管我发现它由于“%$queryString%”或其他原因而容易受到 SQL 注入的影响?任何帮助都非常感谢!

if ( isset( $_POST['queryString'] ) )

  $queryString = $_POST['queryString'];
  if ( strlen( $queryString ) > 0 )
  
    $query = "SELECT game_title, game_id FROM games WHERE game_title LIKE '%$queryString%' || alt LIKE '%$queryString%' LIMIT 10";
    $result = mysql_query( $query, $db ) or die( "There is an error in database please contact support@laglessfrag.com" );
    while ( $row = mysql_fetch_array( $result ) )
    
      $game_id = $row['game_id'];
      echo '<li onClick="fill(\'' . $row['game_title'] . '\',' . $game_id . ');">' . $row['game_title'] . '</li>';
    
  

【问题讨论】:

我不是 php 高手,所以我不会“回答”,但这很容易受到攻击,因为您没有清理您的输入。基本上,用户文本被直接写入查询中,这将允许他们编写类似“'; drop table games;”的内容。和噗!你的桌子会消失。您需要通过 php 的内置 mysql 清理函数之一运行它,它的名称中有转义,我只是无法确切知道它是什么。 @Chris Thompson:这听起来像是一个答案。请将其发布为答案并删除此评论。然后我们可以正确地为您的答案投票。 使用参数化查询。由于使用了缓存的执行计划,您可能会比动态 sql 获得性能改进,并且不必担心清理 - us3.php.net/manual/en/mysqli.prepare.php @S. Lott 我同意,虽然我很伤心,因为这是对问题所在的解释,但我对如何具体解决漏洞没有很好的答案(即我不记得函数名称) 【参考方案1】:

注入漏洞是您将用户提供的数据直接传递到查询中而不对其进行清理。特别是这行是有问题的:

$queryString = $_POST['queryString'];  

如果您在$_POST['queryString'] 周围使用函数mysql_real_escape_string(),这将阻止用户插入自己的代码。

$queryString = mysql_real_escape_string($_POST['queryString']); 

【讨论】:

啊就这么简单?感谢负载 - 期待它会非常复杂:) 正确答案但观点错误。用户提供的数据不需要任何“清理”。 mysql_real_escape_string() 的目的仅仅是分隔符转义。因此,我们用引号括起来的任何数据都必须使用 mysql_real_escape_string() 进行处理,无论是用户输入还是其他任何内容。 @Craig 是的,SQL 注入是谣言多于真实。如果你的语法是正确的,没有什么可以伤害你。 mysql_real_escape_string() 是您必须始终遵循的语法的一部分。但它只能帮助处理数据。对于查询的其他部分,有一些更复杂的事情【参考方案2】:

在将值连接到查询字符串之前,对来自不受信任来源的所有值使用mysql_real_escape_string()。 (作为一般规则,如果您没有将值硬编码到查询字符串中,请将其转义)。例如:

$queryString = mysql_real_escape_string($_POST['queryString']);
$query =  "SELECT game_title, game_id "
        . "FROM games "
        . "WHERE game_title LIKE '%".$queryString."%'" 
        . "|| alt LIKE '%".$queryString."%' "
        . "LIMIT 10";

使用支持准备好的语句的 mysql 适配器通常更容易,这使得忘记清理输入变得更加困难。例如 PHP 有 pdo 或 mysqli

【讨论】:

这是一个有价值的答案,但由于干燥,我给 davethegr8 +1。 实际上 mysql_real_escape_string() 应该用于作为字符串处理的每个值,无论来源是什么。这是 sintax 问题,而不是“保护”。 @Peter 是的,davethegr8 的解释要好得多,绝对值得 +1。我的一半回答是对人们格式化 SQL 的方式感到烦恼。 @Yacoby 列名确实会导致 SQL 注入。而且你不会转义它不是因为不会导致 SQL 注入,而是因为 SQL 语法不允许在标识符周围加上引号。 @Col。 (先前评论的澄清版本)我同意不受信任的来源有点含糊。我的意思是没有必要转义 hardcoded 列名,因为我知道它们不会导致 SQL 注入。

以上是关于如何保护此代码免受 SQL 注入?有点迷茫的主要内容,如果未能解决你的问题,请参考以下文章

哪些是保护输入免受sql注入的最佳php函数以及如何使用它们? [复制]

在 PHP 中使用准备好的语句/存储过程时如何保护自己免受 SQL 注入?

我是不是足够保护我的网站免受 sql 注入?

PHP PDO:保护动态标识符免受 SQL 注入

Pipy:保护 Kubernetes 上的应用程序免受 SQL 注入和 XSS 攻击

如何防止 PHP 中的代码注入攻击?