English 中文(简体)
为什么使用mysql准备的语句比使用常见的转义函数更安全?
原标题:
  • 时间:2009-04-09 02:24:05
  •  标签:

在另一个问题中有一条评论,内容如下:

"When it comes to database queries, always try and use prepared parameterised queries. The mysqli and PDO libraries support this. This is infinitely safer than using escaping functions such as mysql_real_escape_string."

来源

所以,我想问的是:为什么准备好的参数化查询更安全?

最佳回答

我认为这里的人缺少的一点很重要,那就是有了支持参数化查询的数据库,就不用担心逃避了。数据库引擎不会将绑定的变量组合到SQL语句中,然后解析整个过程;绑定的变量是分开的,永远不会被解析为通用SQL语句。

这就是安全性和速度的来源。数据库引擎知道占位符只包含数据,所以它永远不会被解析为完整的SQL语句。当你准备一个语句一次,然后执行多次时,就会出现加速;典型的例子是将多个记录插入到同一个表中。在这种情况下,数据库引擎只需要解析、优化等一次。

现在,一个难题是数据库抽象库。他们有时只是通过将绑定变量插入到SQL语句中并进行适当的转义来伪造它。尽管如此,这还是比自己做要好。

问题回答

首先,你将危险字符的转义留给数据库,这比你这个人安全得多。

…它不会忘记转义,也不会错过任何可能用于注入恶意SQL的特殊字符。更不用说,启动时您可能会获得性能提升!

我对安全不是很精通,但这里有一个解释,我希望能对你有所帮助:

假设您有这样的陈述:

从mydb中选择[integer]

假设在准备时,该语句在我们想象的sql实现中被编译为字节。

           01                  00 00                  23
Opcode for select          Prepared bytes      number of "mydb"
                          for your integer

现在,当您执行时,您将在为准备好的语句保留的空间中插入数字。

相比之下,如果你只使用escape,你可能会在其中插入同样多的胡言乱语,可能会导致内存溢出,或者一些奇怪的sql命令忘记了转义。

因为有了事先准备好的语句,你就不能忘记逃离内容。因此,没有办法引入不安全感。

如果您记得每次调用mysql_query时都要使用mysql_real_sescape_string,那么mysql_real_eescape/string和准备好的语句一样安全,但很容易忘记。

准备好的语句解决了应用程序安全性的根本问题而单纯的数据卫生是不存在的:它们导致数据和指令的完全分离。当两者混淆时,就会产生不安全性。SQL注入和缓冲区溢出都是如此。

(还有其他不安全的方式。)

最好的情况可能不是,但至少同样安全;为什么要冒险?

由于此漏洞,该函数不安全http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string。这就是为什么准备好的语句是首选的,它也能提高性能。





相关问题
热门标签