1

我了解到,使用准备好的语句(参数化查询)可以用于防止 SQL 注入攻击,除了这篇文章中提到的少数例外:PDO 准备好的语句是否足以防止 SQL 注入?.

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

  • 使用参数化查询时,客户端在没有任何数据的情况下将查询发送到服务器进行准备(优化),然后将参数(用户输入或任何)发送到服务器,以便用户数据驻留在原始查询之外。

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

出于这个原因,我没有测试这个例子,因为 using execute(), bind_param(), binVlaue(),binParam()在使用时都在转义数据,所以我们不能用它们发送未转义的数据来测试带有未转义参数的预处理语句的安全性。

4

4 回答 4

4

基本问题是这样的:

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

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

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

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

处理此问题的一种技术是转义在字符串文字中具有特殊含义的字符:

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

另一种方法是将字符串文字完全分开,这样就不会混淆它的开始和结束位置:

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

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

于 2013-09-15T11:38:03.083 回答
2

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

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

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

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

于 2013-09-15T11:40:57.747 回答
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')";

就那么简单

于 2017-04-29T10:01:29.113 回答
0

是的,您可以通过 pdo 和 mysqli 防止 sql 注入

<< 查看演示 >>

使用 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();
于 2017-04-29T09:44:38.397 回答