使用ONLY php防止SQL注入

时间:2011-01-26 15:38:54

标签: php mysql sql-injection

我认为我有一个完整的工作网站,有许多调用MySQL服务器,并在这个网站上做了一些研究,我看到以这种形式制作我的查询:

$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
            mysql_real_escape_string($user),
            mysql_real_escape_string($password));

我可以解决安全问题,但是,正如我所说,我有很多调用MySQL服务器,并且解决问题的最佳方式(直到我的情况)直接转到vars im传递给查询但是使用MySQL函数的whitout因为我不在查询中。让我解释一下,我有这个:

mysql_query("SELECT * FROM `post` WHERE id=" . $_GET['edit']);

我无法对此查询进行修改,因为我在所有代码中都有很多这样的内容,我希望检查var上的注入,$ _GET ['edit']。

如何使用纯PHP检查查询变量的SQL注入?像:

$_GET['edit']=freehack($_GET['edit']);

6 个答案:

答案 0 :(得分:12)

不要这样做。通过将“{1}}参数的值替换为”安全“版本,您将污染输入数据,这可能是其他地方所需要的。

仅在需要在数据库层上使用数据时转义数据。它只需要您花一点时间来修复您的查询,从长远来看将为您节省大量的麻烦。

无论如何,您所做的事情仍然不安全!请参阅:PHP: Is mysql_real_escape_string sufficient for cleaning user input?

你真的应该使用prepared queries with PDO。此外,在查询中使用之前,您应检查用户输入的有效性。

答案 1 :(得分:7)

“我无法对此查询进行修改,因为我在所有代码中都有很多这样的内容”在讨论安全性时是错误的态度。您所拥有的是一个主要的设计问题,可以解决各种安全问题。即使您执行的操作类似于最后描述的过滤方法,也无法确定是否涵盖了所有情况。

您应该使用某种数据库访问类来查询数据库,而不是在整个代码中进行这样的随机调用。通过这种方式,您可以编写一次清理代码,并且绝对可以确保在任何地方都可以调用它。重构是值得的,因为您将获得额外的安全性。

答案 2 :(得分:1)

我认为您可以将查询包装在PDO内。

$unsafe = "SELECT * FROM `post` WHERE id=" . $_GET['edit'];
$DBH->quote($unsafe); // makes query safe.

其中$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

然后你必须编写一些脚本来进行替换。然后我再次认为你应该从头开始重写代码,因为它真的很难看。适当的单元测试,PDO,CSRF保护,OOP等。

答案 3 :(得分:0)

我不会选择“魔术”功能并希望它能够清理变量。这不会解决所有边缘情况,但仍然容易受到攻击。

这是一个很好的例子,是你的第二个查询。如果你mysql_real_escape_string $_GET['edit']变量,它仍然容易受到SQL注入甚至的攻击。<​​/ p>

您需要做的是验证收到的所有数据,并检查它是否是您期望的数据类型。

if (SomeValidator::validateInt($_GET['edit'])) {
    // OK, we continue //
} else {
    // Display error, but don't continue ! //
}

消毒只是确保数据正确显示并且不会导致问题。您不应该依赖于清理来验证数据。

如果您想正确完成验证和清理,可以使用ESAPI for PHP

答案 4 :(得分:0)

我建议使用PDO接口或MySQLi接口作为支持使用准备好的查询。使用准备好的查询是有效且始终如一地保护自己SQL注入攻击的唯一方法。我个人推荐PDO over mysqli,因为它为您的数据库提供了一个数据库无关的接口,以防您需要切换数据库。即使您永远不需要切换数据库,最好只需要学习1个接口,以防您需要使用不同的数据库来处理另一个项目。

答案 5 :(得分:0)

  1. 避免在整个应用程序的不同位置重复相同的查询 - 随着事情的发展,您需要维护多个版本,并且它们几乎总是不同步。准备好的查询对我来说听起来不错(我不是真正的PHP人),或者如果你必须采用另一种方式设置中央参考库并将查询存储在那里,那么在你的app中需要它们时引用它们。 / p>

  2. 不存储编码数据,很容易忘记哪些变量是编码的,哪些不是,加上一旦你不得不将数据用于不同编码的目的,你就会遇到麻烦。在此过程中尽可能延迟编码,最好是在需要编码的最终情况下进行编码,以便快速检查可以显示它已完成。

  3. 如果必须...... SQL注入是一个明显的类型安全问题。如果你知道你期望一个整数参数,“1; drop table users; - ”是无效的输入,即使它没有任何危险字符或转义序列。不要只是检查字符串或其他什么,请确保当你想要一个特定的类型时,你会得到它并且其他输入会引发错误。