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

问题描述:

从历史上看,我一直使用PHP MySQLi准备好的绑定参数查询是否安全?

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中结束。
准备阶段提供的查询是静态的。

这不是那么简单。你可以用它代替插值应用程序变量为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代码,以帮助你找到你忽略使用上述两种技术的地方。

+0

是的。注意到你不能执行ORDER BY?位参数。好答案。 – 2009-10-13 22:17:06

+0

我得到了一个downvote? Downvoter,你应该描述你为什么认为这个答案不令人满意。也许我可以改进它。 – 2015-02-16 07:20:31

是的。使用准备好的查询将会跳过参数。

+0

简短,甜美,准确。 – ceejayoz 2009-10-13 17:04:46

+0

谢谢。只是想确保我没有失去明显的东西。我倾向于这样做。 – 2009-10-13 17:14:06

将参数绑定到预处理语句时,会自动转义数据,因此在发送之前不应将其转义。双逃脱通常是一件坏事。至少,它会产生丑陋的结果,并在稍后出现额外的逃脱字符。