PHP-mysqli_set_charset()和SQL注入

时间:2019-03-19 18:22:56

标签: php mysql security

在这里和其他地方,我读过几篇文章说,如果首先将用户输入的每个字符串(以及在数据库查询中使用的字符串)首先放入mysqli_real_escape_string(),则使用mysqli_set_charset()可以防止SQL注入。

但是,没有什么比准备好的语句更安全了。不是其中任何一个的专家,代码中的这些行是真的吗?

$input = "This is an input string";
mysqli_set_charset($conn, 'utf8');
$input = mysqli_real_escape_string($conn, $input);

足以防止SQL注入吗?当然,我假设实际上每个输入都被转义了。就我目前的理解而言,应该是这样,但是我怀疑我目前的理解是否足够。我知道在某些情况下mysqli_real_escape_string()可能会失败,但这些情况似乎取决于脆弱的字符集(根据我目前的理解)。

1 个答案:

答案 0 :(得分:2)

这里的关键是永远不要使用mysqli_real_escape_string,除非您有充分的理由。组成一个简单的查询不是一个。

mysqli_real_escape_string 可以防止SQL注入。具有占位符值 的预备语句将防止SQL注入。这是一个重要的区别。

考虑以下代码:

 $a = $_POST['a'];
 $b = $_POST['b'];
 $c = $_POST['c'];
 $d = $_POST['d'];
 // ...
 $a = $conn->real_escape_string($a);
 $a = $conn->real_escape_string($b);
 $c = $conn->real_escape_string($c);
 $d = $conn->real_escape_string($d);

 $conn->query("INSERT INTO x (a,b,c,d) VALUES ('$a', '$b', '$c', '$d')");

由于一个小错误,它中有一个SQL注入错误。微小的错误并不重要,即使是这样的单个漏洞也足以完全破坏您的应用程序。

相反,使用带占位符值的预准备语句:

 $stmt = $conn->prepare('INSERT INTO x (a,b,c,d) VALUES (?,?,?,?)');
 $stmt->bind_param('ssss', $_POST['a'], $_POST['b'], $_POST['c'], $_POST['d']);
 $stmt->execute();

即使在此处输入错误,也可能发生的最糟糕情况是查询失败或插入错误的数据。您没有SQL注入错误。您的应用程序不会受到威胁。我什至建议您在定义查询时使用单引号,这样您就永远不会尝试使用变量插值(这是一种注入形式)。

还值得注意的是,bind_param方法的代码更少,并且可读性更高。真的没有理由对这种情况使用手动转义。