Mysqli_escape_string或Prepared语句如何从SQL注入中保存我

时间:2014-06-26 11:06:54

标签: php mysqli prepared-statement sql-injection

我正在阅读有关SQL-Injection

的Stack over flow的大量论坛和答案

我开始知道这是SQL注入的基本级别

  $_POST['name'] = 'xyz;DROP Table users';
  mysqli_query ('select * from abc where name='."$_POST['name']")

要防止这种情况

  1. 对来自用户的任何输入使用mysqli_escape_stirng可以保存我的SQl-injection
  2. 使用PDO和prepare语句也可以使我免于SQL注入
  3. Q1。我想知道的是如何将数据传递给Mysqli_escape_string可以使我免于SQL注入

      $safe_variable = mysqli_escape_String($connection ,$_POST['name'];
    

    mysqli_escape_string如何仅保存POST数据中的“XYZ”并保留部分的其余部分(如果是这种情况)

    Q2。 PDO将如何从SQL注入中保存我

      $stmt = $dbh->prepare("select * from ABC where name = :name");
      $stmt->bindParam(':name',$name);
      $name = $_POST['name'];
      $stmt->execute();
    

    在这方面有任何帮助,非常感谢

3 个答案:

答案 0 :(得分:3)

将用户输入合并到SQL中的问题在于,在生成的SQL中,您无法分辨开发人员提供哪些部分以及用户提供哪些部分。这就是开发人员必须确保用户输入按预期解释的原因。

这是字符串转义函数参数化的来源:

字符串转义函数,例如mysqli_real_escape_string处理该值,以便可以在string literal中安全地使用它,而不必担心它可能被解释为除字符串数据之外的任何其他内容。< / p>

但是,重要的是要注意,该值实际上放在字符串文字中,而不是其他地方,因为它仅用于特定目的,即。例如,它确保传递的数据仅在放置在字符串文字中时才被解释为字符串数据。不幸的是,PHP手册没有提到字符串文字部分。

由准备好的语句实现的

参数化将SQL和数据参数分开。因此,不能混淆SQL代码和提供的数据。对于服务器端预处理语句,首先准备语句只包含参数占位符,然后传递参数值以供执行。无论何时遇到参数,DBMS都会使用相应的参数值。


至于你的具体例子:

  

我想知道如何将数据传递给Mysqli_escape_string可以让我免于SQL注入

  $safe_variable = mysqli_escape_String($connection ,$_POST['name'];
     

mysqli_escape_string如何仅保存POST数据中的“XYZ”并保留部分的其余部分(如果是这种情况)

它不是因为您没有将值放在字符串文字中。但是,以下方法可行:

mysqli_query("select * from abc where name='$safe_variable'")


  

PDO如何从SQL-Injection中拯救我

  $stmt = $dbh->prepare("select * from ABC where name = :name");
  $stmt->bindParam(':name',$name);
  $name = $_POST['name'];
  $stmt->execute();

如前所述,您通过准备语句明确说明了SQL的样子。然后传递参数以供执行。由于参数化的SQL及其参数是分开的,它们不会混合,并且传递的参数值不能被误认为是SQL。

答案 1 :(得分:1)

我认为大多数SQL转义函数都是这种情况:

他们逃离了;'"等控件字符,...

所以你的字符串

xyz;DROP Table users

将被函数转义为

xyz\;DROP Table users

所以你的字符串现在不再是一个有效的SQL命令了。

但请注意存储在数据库中的数据中的HTML标记。

如果我插入例如

<script>alert('foobar');</script>

这将存储在DB中,不受SQL转义函数处理。如果再次在某处打印出该字段,则JS将由访问者浏览器执行。

因此,请使用附加htmlspecialchars()htmlentities()来清理用户输入。准备好的陈述也是如此。

答案 2 :(得分:1)

Q1:

  

mysql(i)_real_escape_string()调用MySQL的库函数   mysql(i)_real_escape_string,它将反斜杠添加到以下内容中   字符:\x00\n\r\'"\x1a

http://php.net/mysqli_real_escape_string

请注意,这取决于字符编码(在这种情况下工作是SET NAMES ...(安全风险!!!),应该使用$mysqli->set_charset('utf8');!)。 (您可以在我的帖子Mastering UTF-8 encoding in PHP and MySQL中阅读有关编码的信息。)

它如何阻止SQL注入? - 它可以通过转义'等来防止破坏变量上下文,事实是,mysql_querymysqli_query每个查询只执行一个查询< / em>,这意味着它只是忽略 ;DROP Table users

mysqli_real_escape_string 不会阻止插入DROP DATABASE等代码。

在这种情况下,只有PDO和/或mysqli_multi_query容易受到攻击。

Q2:

首先将语句发送到服务器,然后将绑定的变量分开发送,然后执行语句,在这种情况下,安全性由数据库库提供,而不是由客户端库提供。你应该优先考虑。

这意味着,您首先将$dbh->prepare("select * from ABC where name = :name");发送到服务器,并且数据库知道您的绑定参数将插入:name占位符,并且会自动将其正确包装以不会中断它的假设背景。数据库将尝试查找name xyz;DROP Table users的值,并且它不会执行任何命令,只需填充该变量空间。