PHP MySQLi是否准备好绑定参数的查询安全?

时间:2009-10-13 17:02:48

标签: php mysqli prepared-statement

历史上,我一直使用

mysql_real_escape_string()

用于从最终触及数据库的用户派生的所有输入。

现在我已经完全转换为MySQLi并且我正在使用带有绑定参数的准备查询,我是否有效地消除了SQL注入攻击的可能性?

我说我不再需要

mysql_real_escape_string()?

这是我的理解和我的项目的基础: http://sourceforge.net/projects/mysqldoneright/files/Base/MysqlDoneRight-0.23.tar.gz/download

这不是我想弄错的事情,虽然现在我已经发布了它,它也可能会影响其他人。

现在,所有用户提供的输入都将以bind_parms结尾 准备阶段提供的查询是静态的。

3 个答案:

答案 0 :(得分:13)

是。使用准备好的查询将转义参数。

答案 1 :(得分:6)

这不是那么简单。您可以使用绑定参数,而不是仅将应用程序变量插入到SQL表达式中,而不是文字值

$sql = "SELECT * FROM MyTable WHERE id = ".$_GET["id"]; // not safe

$sql = "SELECT * FROM MyTable WHERE id = ?"; // safe

但是,除了字面值之外,如果你需要将查询的一部分动态化呢?

$sql = "SELECT * FROM MyTable ORDER BY ".$_GET["sortcolumn"]; // not safe

$sql = "SELECT * FROM MyTable ORDER BY ?"; // doesn't work!

该参数将始终被解释为值,而不是列标识符。您可以使用ORDER BY 'score'运行查询,该查询与ORDER BY score不同,并且使用参数将被解释为前者 - 常量字符串'score',而不是命名列中的值score

因此,在很多情况下,您必须使用动态SQL并将应用程序变量插入到查询中以获得所需的结果。在这些情况下,查询参数无法帮助您。你仍然需要保持警惕并采取防御措施来防止SQL注入漏洞。

没有框架或数据访问库可以为您完成此工作。您始终可以构造包含SQL注入漏洞的SQL查询字符串,并在数据访问库看到SQL查询之前执行此操作。那怎么知道什么是故意的,什么是缺陷呢?

以下是实现安全SQL查询的方法:

  • 过滤输入。跟踪插入SQL查询的所有变量数据。使用输入filters删除非法字符。例如,如果您期望一个整数,请确保输入被约束为整数。

  • 转义输出。此上下文中的输出可以是您发送到数据库服务器的SQL查询。您知道可以对值使用SQL查询参数,但列名称呢?您需要一个标识符的转义/引用功能,就像旧的mysql_real_escape_string()用于字符串值一样。

  • 代码评论。让某人成为第二双眼睛并查看您的SQL代码,以帮助您找到您忽略使用上述两种技术的地方。

答案 2 :(得分:1)

将参数绑定到预准备语句时,它会自动转义数据,因此在发送之前不应将其转义。双重逃避通常是一件坏事。至少,它会在以后使用额外的转义字符产生难看的结果。