【发布时间】:2010-10-18 11:14:29
【问题描述】:
另一个问题中有一条评论如下:
“当涉及到数据库查询时, 总是尝试使用准备好的 参数化查询。 mysqli 和 PDO 库支持这一点。这是 比使用转义更安全 功能如 mysql_real_escape_string。”
那么,我想问的是:为什么准备好的参数化查询更安全?
【问题讨论】:
标签: php mysql security sql-injection prepared-statement
另一个问题中有一条评论如下:
“当涉及到数据库查询时, 总是尝试使用准备好的 参数化查询。 mysqli 和 PDO 库支持这一点。这是 比使用转义更安全 功能如 mysql_real_escape_string。”
那么,我想问的是:为什么准备好的参数化查询更安全?
【问题讨论】:
标签: php mysql security sql-injection prepared-statement
我认为这里的人们缺少的重要一点是,使用支持参数化查询的数据库,无需担心“转义”。数据库引擎不会将绑定的变量组合到 SQL 语句中,然后解析整个事情;绑定的变量是独立的,永远不会被解析为通用 SQL 语句。
这就是安全性和速度的来源。数据库引擎知道占位符仅包含数据,因此它永远不会被解析为完整的 SQL 语句。当您准备一个语句然后多次执行它时,速度就会提高;将多条记录插入同一个表的规范示例。这种情况下,数据库引擎只需要解析、优化等一次。
现在,一个问题是数据库抽象库。他们有时会通过将绑定变量插入到带有适当转义的 SQL 语句中来伪造它。不过,这比自己做要好。
【讨论】:
首先,您将危险字符的转义留给数据库,这比您人类安全得多。
...它不会忘记逃跑,也不会错过任何可用于注入恶意 SQL 的特殊字符。更不用说,您可能会在启动时获得性能提升!
【讨论】:
我对安全性不是很精通,但这里有一个解释,希望对您有所帮助:
假设您有这样的声明:
从 mydb 中选择 [整数]
假装当你准备它时,该语句在我们想象的 sql 实现中被编译成字节。
01 00 00 23
Opcode for select Prepared bytes number of "mydb"
for your integer
现在,当您执行时,您会将数字插入为准备好的语句保留的空间中。
如果你只是使用转义,你可能会在其中插入尽可能多的乱码,并可能导致内存溢出,或者一些他们忘记转义的奇怪 sql 命令。
【讨论】:
因为使用准备好的语句,您不能忘记转义内容。所以没有办法引入不安全感。
如果您记得每次调用 mysql_query 时都使用 mysql_real_escape_string,则 mysql_real_escape_string 与准备好的语句一样安全,但很容易忘记。
【讨论】:
准备好的语句解决了fundamental problem of application security 单纯的数据清理无法解决的问题:它们导致数据和指令完全分离。当两者混淆时,结果就是不安全。 SQL 注入和缓冲区溢出都是如此。
(还有其他不安全的方法。)
【讨论】:
最好的情况,可能不是,但至少同样安全;为什么要冒险?
【讨论】:
由于此漏洞http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string,该函数不安全。这就是为什么首选准备好的语句并且它也可以提高性能的原因。
【讨论】: