mysqli_real_escape_string - 100%安全的例子

时间:2015-12-02 20:25:26

标签: mysqli sql-injection

我知道已经有很多关于这个话题的问题。而且我也知道要走的路是准备好的陈述。但是,我仍然没有完全理解以下是否或如何成为安全问题:

$mysqli = new mysqli("localhost", "root", "", "myDatabase");
$mysqli->set_charset("utf8");
$pw = mysqli_real_escape_string($mysqli,$_POST['pw']);
$username = mysqli_real_escape_string($mysqli,$_POST['username']);

$str = "SELECT * FROM users WHERE id='".$id."' AND username='".$username."'";
$result = $this -> mysqli -> query($qstr);

if($result->num_rows > 0){
    //user logged in
}

我从注射备忘单中尝试了许多不同的输入,但找不到任何通过查询的内容。例如。如果我输入“;”然后$ result变为false,因为据我所知,一个查询不能包含两个单独的语句。任何带有'或'的输入都被消毒了 mysqli_real_escape_string。

请您解释一下上面的代码如何被利用?如果你有一个解释它的链接,我也非常乐意阅读它!

干杯

编辑:在这个答案中已经回答了这个问题:

SQL injection that gets around mysql_real_escape_string()

然而,这个问题是关于mysql的旧版本而不是mysqli。其次,最多投票的答案陈述以下可以绕过它的例子:

mysql_query('SET NAMES gbk');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");

但是我不完全理解这一点。第一行

mysql_query('SET NAMES gbk');

无法从外面设置,对吗?这只是一个例子,如果有人在他的程序中设置'gbk'。所以,如果我使用

$mysqli->set_charset("utf8");

并且还使用了

id='".$id."' (single quotes around $id) 
那么我会100%安全,对吗?

1 个答案:

答案 0 :(得分:2)

您孤立和简化的示例在技术上是安全的。

但是,它仍然存在两个问题:

  • 假设:问题的陈述完全基于mysqli_real_escape_string()与任何安全性问题有关的假设。这不过是一个严重的幻想。这是一个字符串格式化功能,仅作为副作用,可以防止SQL注入。但是,这种保护既不是功能的目的也不是目的。因此,永远不要将其用于此目的。
  • 您提出的代码的
  • 固有的可分离性。保护由三个部分组成:
    • 设置正确的编码
    • 转义特殊字符
    • 将转义的值括在引号中

不仅这些强制性措施could be forgotten中的一些事实,而且问题的陈述只强调了一个部分-转义。总是着重于逃避,而几乎没有提到另外两个措施。只要看看您的问题-您的意思是 code ,但询问有关 function 的问题。因此,对您提出的问题的任何字面回答都会给人致命的错误印象,即mysqli_real_escape_string()没问题。

简而言之,问题陈述有助于促进与PHP相关的错觉中最危险的事情:该函数可以防止SQL注入。

与这个复杂的三部分方程式不同,准备好的语句构成了不可分离的度量。你不能忘记一个部分。您不能滥用它。尝试使用mysqli_real_escape_string()保护标识符,直到实际注入发生之前,它都不会被忽略。尝试为标识符准备的语句-并得到一个错误。