29

另一个问题中有一条评论如下:

“当涉及到数据库查询时,请始终尝试使用准备好的参数化查询。mysqli 和 PDO 库支持这一点。这比使用 mysql_real_escape_string 等转义函数要安全得多。”

来源

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

4

7 回答 7

48

我认为这里的人们缺少的重要一点是,使用支持参数化查询的数据库,无需担心“转义”。数据库引擎不会将绑定的变量组合到 SQL 语句中,然后解析整个事情;绑定的变量是分开的,永远不会被解析为通用 SQL 语句。

这就是安全性和速度的来源。数据库引擎知道占位符仅包含数据,因此它永远不会被解析为完整的 SQL 语句。当您准备一条语句然后多次执行它时,速度就会提高;将多条记录插入同一个表的规范示例。在这种情况下,数据库引擎只需要解析、优化等一次。

现在,一个问题是数据库抽象库。他们有时会通过将绑定变量插入到带有适当转义的 SQL 语句中来伪造它。不过,这比自己做要好。

于 2009-04-09T03:07:11.417 回答
7

一方面,您将危险字符的转义留给数据库,这比您人类安全得多。

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

于 2009-04-09T02:28:42.320 回答
5

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

假设您有如下声明:

从 mydb 中选择 [整数]

假装当你准备它时,语句在我们想象的 sql 实现中被编译成字节。

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

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

比较一下,如果你只是使用转义,你可能会在其中插入尽可能多的乱码,并可能导致内存溢出,或者他们忘记转义的一些奇怪的 sql 命令。

于 2009-04-09T02:39:54.867 回答
3

因为使用准备好的语句,您不能忘记转义内容。所以没有办法引入不安全感。

如果您记得每次调用 mysql_query 时都使用 mysql_real_escape_string,则 mysql_real_escape_string 与准备好的语句一样安全,但很容易忘记。

于 2009-04-09T02:40:44.990 回答
1

准备好的语句解决了单纯的数据清理无法解决的应用程序安全性问题:它们导致数据和指令的完全分离。当两者混淆时,结果就是不安全。这适用于 SQL 注入和缓冲区溢出。

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

于 2015-12-09T07:35:38.997 回答
0

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

于 2009-04-09T02:39:51.607 回答
0

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

于 2009-04-09T02:45:01.330 回答