PDO和MySQLi准备语句是否可以防止SQL注入,即使没有转义用户输入?

时间:2013-09-15 11:20:45

标签: php pdo mysqli escaping sql-injection

我了解到使用预准备语句(参数化查询)可用于防止SQL注入攻击,本文中提到的例外情况很少:Are PDO prepared statements sufficient to prevent SQL injection?

我的问题是预备语句如何阻止SQL注入?到目前为止我学到了什么:

  • 使用参数化查询时,客户端将查询发送到服务器进行准备(优化),不需要任何数据,稍后,参数(用户输入或任何)将被发送到服务器,以便用户数据驻留在外部原始查询。

  • 使用准备好的查询时,如果未转义用户数据,则不会阻止任何SQL注入。

出于这个原因,我没有测试该示例,因为使用execute()bind_param()binVlaue()binParam()都在使用时转义数据,以便我们可以' t与他们一起发送未转义的数据,以测试带有未转义参数的预准备报表的安全性。

4 个答案:

答案 0 :(得分:4)

基本问题是:

$value = "Foo' OR 1 = 1 --";
$query = "SELECT id FROM users WHERE name = '$value'";

如上连接,这是实际的查询:

SELECT id FROM users WHERE name = 'Foo' OR 1 = 1 --'

这里的问题是字符',它在字符串文字上下文中具有终止字符串文字的特殊含义。

处理此问题的一种方法是转义字符,这些字符在字符串文字中具有特殊含义:

SELECT id FROM users WHERE name = 'Foo\' OR 1 = 1 --'

另一种方法是将字符串文字完全分开,因此不会混淆它的起点和终点:

query: SELECT id FROM users WHERE name = $1
   $1: Foo' OR 1 = 1 --

前一种技术是转义,后者是参数化查询。您只需要使用其中一个。如果你转义了你也参数化的值,你只需要用不必要的反斜杠来搞乱你的值。

答案 1 :(得分:2)

SQL注入意味着用户输入用作SQL语句的一部分。

如果您使用预准备语句,则用户输入将被视为内容而不是SQL命令的一部分。

但是,如果通过将用户输入字符串连接在一起来构建SQL命令,那么再次引入SQL注入漏洞。

因此,简而言之,使用准备好的查询是安全的,但用户输入应仅用作参数,而不是查询文本的一部分。

答案 2 :(得分:0)

是的,您可以通过pdo和mysqli

阻止sql注入

<< View Demo >>

使用PDO:

步骤1:连接数据库

在这里我创建数据库“inphplab”。您可以根据自己的要求进行更改。

$dbConnection = new PDO('mysql:dbname=inphplab;host=127.0.0.1;charset=utf8', 'root', '');

$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

步骤2:将数据插入“员工”表

这里我采取两个变量并声明姓名和地址如下。

$name = "bapuRocks";
$address = "India";

$stmt = $dbConnection->prepare("INSERT INTO employee ( name, address) VALUES ( :name, :address )");

$stmt->bindValue(':name', $name);
$stmt->bindValue(':address', $address);

printf("%s Row inserted.\n", $stmt->execute());

使用MySQLi:

步骤1:连接数据库

在这里我创建数据库“inphplab”。您可以根据自己的要求进行更改。

$mysqli = new mysqli('localhost', 'root', '', 'inphplab');

/* check connection */

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

步骤2:将数据插入/删除到“员工”表

这里我采取两个变量并声明姓名和地址如下。

$stmt = $mysqli->prepare("INSERT INTO employee SET `name`=?,`address`=?");
$stmt->bind_param('ss', $name, $address);

$name = 'Yuvraj Sinh';
$address = 'India';

/* execute prepared statement */
$stmt->execute();

printf("%s Row inserted.\n", $stmt->affected_rows);

/* close statement and connection */
$stmt->close();

/* Clean up table CountryLanguage */
$mysqli->query("DELETE FROM employee WHERE name='Bharat Sinh'");
printf("%s Row deleted.\n", $mysqli->affected_rows);
/* close connection */
$mysqli->close();

答案 3 :(得分:0)

防止SQL注入的最简单方法是使用简单的hex2str()函数将所有用户输入转换为HEX,然后使用str2hex()将其转换回来 - 这可确保所有数据都是安全的。

 function strToHex($string){
      $hex = '';
      for ($i=0; $i<strlen($string); $i++){
          $ord = ord($string[$i]);
          $hexCode = dechex($ord);
          $hex .= substr('0'.$hexCode, -2);
      }
      return strToUpper($hex);
  }
  function hexToStr($hex){
      $string='';
      for ($i=0; $i < strlen($hex)-1; $i+=2){
          $string .= chr(hexdec($hex[$i].$hex[$i+1]));
      }
      return $string;
  }

修改

$ID = strToHex($_GET["ID"]);
$COL1 = strToHex($_GET["COL1"]);
$COL2 = strToHex($_GET["COL2"]);

$query = "insert into my_db.my_table(ID, COL1, COL2) VALUES('$ID','$COL1','$COL2')";

简单就是那个