使用sql转义的动态mysql查询是否与预准备语句一样安全?

时间:2011-01-23 02:35:20

标签: mysql security sql-injection prepared-statement

我有一个应用程序,通过结合mysql(mysqli)真正的转义字符串使用动态mysql查询将大大受益。如果我通过mysql运行从用户收到的所有数据真正的转义它是否与使用mysql预处理语句一样安全?

3 个答案:

答案 0 :(得分:17)

是的,但是合格的是。

您需要正确地逃避100%的输入。您需要正确设置字符集(如果您使用的是C API,则需要调用mysql_set_character_set()而不是SET NAMES)。如果你错过了一件小事,那你很脆弱。所以是的,只要你做的一切都正确......

这就是很多人会推荐准备好的查询的原因。不是因为它们更安全。但因为他们更宽容......

答案 1 :(得分:4)

绝对没有。

虽然标题中的问题含糊不清,可以被解释为“动态的mysql查询每个部分正确格式化 ... “因此有一个肯定的答案,身体中的问题是

  

如果我通过mysql运行从用户收到的所有数据真正的转义它是否与使用mysql预处理语句一样安全?

如果你仔细看看这个问题,你会明白这只是一个魔术引语化身!这种耻辱,弃用和删除功能的目的正是“通过转义运行所有用户输入” 现在每个人都知道魔术引用很糟糕。 为什么积极回答呢?

好吧,它似乎需要再次解释,为什么批量转义是坏的。

问题的根源是一个非常强烈的错觉,几乎每个PHP用户都共享:
每个人都有一种奇怪的信念,即逃避对“危险角色”做什么(他们是什么?)使他们“安全”(怎么样?)。不用说,这只是一个完全垃圾。

事实是:

  • 逃避不要“消毒”任何事情。
  • 逃避与注射无关。
  • 转义与用户输入无关。

转义只是一个字符串格式而没有别的 当您需要它时 - 尽管注射可能,但您需要它 当你不需要它时 - 即使是一点也不会有助于注射。

说到与准备好的陈述的区别,至少有一个问题(已在sql-injection标签下多次提及):
像这样的代码

$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);
$query = "SELECT * FROM someTable WHERE somevalue = $clean";

将帮助您免受注射 因为逃避只是一个字符串格式化设施,而不是任何方式的防喷器 去搞清楚。

然而,逃避与准备好的陈述有一些共同点:
如果

,他们都不能保证你注射
  • 您仅使用它来对抗臭名昭着的“用户输入”,而不是作为构建ANY查询的严格规则,尽管有数据源。
  • 如果您需要插入不是数据而是标识符或关键字。

为了安全起见,请参阅我的回答解释FULL sql injection protection how-to

长话短说:只有在对初始陈述做出两个必要的更正和一个补充时,你才能认为自己是安全的:

  

如果我通过mysql真实转义运行从用户收到的所有数据并始终将其括在引号中(并且,正如ircmaxell所述,使用mysqli_set_charset()使mysqli_real_escape string()实际上做它的工作(在极少数情况下使用像GBK这样的奇怪编码))它是否与使用mysql预处理语句一样安全?

遵循这些规则 - 是的,它将与本机准备的语句一样安全。

答案 2 :(得分:1)

我认为@ircmaxell是正确的。

作为后续行动,请注意这类事情 我曾经一直这样做:

<?php

//sanitize the dangerous posted variable...
$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);

//...and then forget to use it!
$query = "SELECT * FROM someTable WHERE somevalue = '{$_POST['some_dangerous_variable']}'";

?>

当我说“习惯做”时,我的意思是我最终放弃并开始使用准备好的陈述!