4

在对上一个问题的评论中,有人说以下 sql 语句打开了我的 sql 注入:

select
    ss.*,
    se.name as engine,
    ss.last_run_at + interval ss.refresh_frequency day as next_run_at,
    se.logo_name    
from 
    searches ss join search_engines se on ss.engine_id = se.id
where
    ss.user_id='.$user_id.'
group by ss.id
order by ss.project_id, ss.domain, ss.keywords

假设$userid变量被正确转义,这如何让我变得脆弱,我能做些什么来修复它?

4

7 回答 7

15

每个值得使用的 SQL 接口库都有某种对绑定参数的支持。不要试图变得聪明,只是使用它。

你可能真的,真的认为/希望你已经正确地逃脱了一些东西,但这只是不值得你不这样做的时间。

此外,一些数据库支持准备好的语句缓存,因此正确执行也可以为您带来效率提升。

更简单、更安全、更快。

于 2008-11-25T04:35:03.197 回答
6

假设它被正确地逃脱,它不会让你变得脆弱。问题是正确地转义比乍看之下更难,并且每次执行这样的查询时,您都会谴责自己正确地转义。如果可能,避免所有这些麻烦并使用准备好的语句(或绑定参数或参数化查询)。这个想法是允许数据访问库正确地转义值。

例如,在 PHP 中,使用mysqli

$db_connection = new mysqli("localhost", "user", "pass", "db");
$statement = $db_connection->prepare("SELECT thing FROM stuff WHERE id = ?");
$statement->bind_param("i", $user_id); //$user_id is an integer which goes 
                                       //in place of ?
$statement->execute();
于 2008-11-25T04:35:01.870 回答
2

如果$user_id被转义,那么您应该不会受到 SQL 注入的攻击。

在这种情况下,我还要确保 $user_id 是数字或整数(取决于所需的确切类型)。您应该始终将数据限制为最严格的类型。

于 2008-11-25T04:36:22.290 回答
1

如果它被正确地转义和验证,那么你就没有问题。

当没有正确转义或验证时,就会出现问题。这可能是由于编码草率或疏忽而发生的。

问题不在于特定实例,而在于模式。这种模式使 SQL 注入成为可能,而另一种模式则使其成为不可能。

于 2008-11-25T04:35:53.943 回答
1

所有答案都是好的和正确的,但我觉得我需要补充一点,prepare/execute范式也不是唯一的解决方案。您应该有一个数据库抽象层,而不是直接使用库函数,这样的层是显式转义字符串参数的好地方,无论您是让prepare做还是自己做。

于 2008-11-25T05:00:48.167 回答
1

我认为这里的“正确转义”是关键字。在您的最后一个问题中,我假设您的代码是从您的生产代码中复制粘贴的,并且由于您询问了有关三个表连接的问题,因此我还假设您没有进行正确的转义,因此我对SQL 注入攻击。

要回答您的问题,正如这里很多人所描述的那样,如果变量已“正确转义”,那么您就没有问题。但是为什么要这样麻烦自己呢?正如一些人所指出的,有时正确转义并不是一件简单的事情。PHP 中有一些模式和库使 SQL 注入成为不可能,我们为什么不直接使用它呢?(我还故意假设您的代码实际上是 PHP)。Vinko Vrsalovic的回答可能会为您提供有关如何解决此问题的想法。

于 2008-11-25T05:09:58.803 回答
0

这样的声明并不是真正的问题,它是“安全的”,但是我不知道你是如何做到这一点的(在 API 堆栈上一级)。如果使用字符串操作将 $user_id 插入到语句中(就像让 Php 自动填写语句一样),那么它很危险。

如果它使用绑定 API 填充,那么你准备好了。

于 2008-11-25T04:35:37.533 回答