【问题标题】:Am I immune to SQL injections if I use stored procedures?如果我使用存储过程,我对 SQL 注入免疫吗?
【发布时间】:2008-10-27 13:39:08
【问题描述】:

让我们说一下 MySQL 数据库(如果重要的话)。

【问题讨论】:

    标签: database security stored-procedures sql-injection


    【解决方案1】:

    不,您不会完全安全。正如其他人所提到的,参数化查询始终是可行的方法——无论您如何访问数据库。

    这有点像一个都市传说,使用 procs 你是安全的。我认为人们产生这种错觉的原因是因为大多数人认为您将使用代码中的参数化查询调用 procs。但是,如果您不这样做,例如,如果您执行以下操作,那么您就会敞开心扉:

    SqlCommand cmd = new SqlCommand("exec @myProc " + paramValue, con);
    cmd.ExecuteNonQuery();
    

    因为您使用的是来自最终用户的未经过滤的内容。再一次,他们所要做的就是终止线路(“;”),添加他们的危险命令,然后繁荣 - 你被冲洗了。

    (顺便说一句,如果您在网络上,请不要从浏览器的查询字符串中获取未经过滤的垃圾信息——这很容易对您的数据做出极其糟糕的事情。)

    如果您将查询参数化,您的状态会好得多。但是,正如其他人在这里提到的那样,如果您的 proc 仍在生成动态 SQL 并执行它,则可能仍然存在问题。

    我应该注意我不是反进程。 Procs 对于解决数据访问的某些问题非常有帮助。但是 procs 不是对 SQL 注入的“灵丹妙药”。

    【讨论】:

      【解决方案2】:

      只有始终使用参数化查询,才能免受 SQL 注入的影响。如果您在任何地方都使用适当的转义,您几乎不会受到 SQL 注入的影响(但是转义例程中可能存在并且已经存在错误,因此它不像参数那样万无一失)。

      如果您调用存储过程,通过串联添加参数,我仍然可以在输入字段之一的末尾添加随机查询 - 例如,如果您有 CALL CheckLogin @username='$username', @ password='$password',$-things 代表直接连接的变量,没有什么能阻止我将 $password 变量更改为 "'; DROP DATABASE; --"。

      显然,如果您事先清理输入,这也有助于防止 SQL 注入,但这可能会过滤掉不应清理的数据。

      【讨论】:

      • +1 表示存储过程可以保护你,-100 表示发帖伪君子。
      • @RandyMorris:我不是这么说的。我的意思是,如果您正在调用存储过程,那么它是否安全并不重要,除非您的调用也是安全的。换句话说,仅使用 SP 是不够的,因为如果您创建查询以通过连接调用 SP,您仍然容易受到 SQL 注入的影响,并且如果 SP构建一个动态查询并执行它。这与我在您正在考虑的评论中的观点没有什么不同:stackoverflow.com/questions/2768692/…
      • 这就像说“反对说密码有助于安全,它只有在它不为空时才有效。”
      【解决方案3】:

      这取决于你的存储过程做什么。如果他们根据参数动态生成 SQL,然后执行该 SQL,那么您仍然容易受到攻击。否则,您很有可能会好起来 - 但我不敢听起来 100% 自信!

      【讨论】:

      • 我想不出为什么要在存储过程中完成此操作。有趣的是知道它可以做到。
      • @Alllain:你的意思是看不到存储过程中生成动态SQL的原因,还是看不到使用参数在存储过程中生成动态SQL的原因提供给程序?
      • @Michael... 必须是客户端人员。认为数据库只是一个扫帚柜,有很多空间来存储他的对象的关系表示......呵呵
      • 是的,这是一个扫帚柜。不过说真的,在存储过程中做这种事情似乎很奇怪。并不是说我想不出一些复杂的要求,我只是想不出比在客户端构建它然后将其发送下来更容易的情况。纠正我。
      • SP 允许更简洁的 PHP/ASP(.NET) 代码,例如,如果您想保留记录的旧版本,在实际更新旧版本时插入新版本记录。然后,SP 可以找出哪些字段引用了您的表,并使用动态 SQL 使用新记录 ID 更新它们。
      【解决方案4】:

      不。如果您正在构建调用存储过程的 SQL,那么您仍然是目标。

      您应该在客户端创建参数化查询。

      【讨论】:

      • 每个 SQL 都应该在数据库中。客户端应该有一个运行查询的过程。任何其他方式都意味着架构师不知道对数据库结构的依赖关系。无法从您的网站告诉您首选的 RDBMS,但这是 Oracle 的强烈推荐
      • @Mark:即使所有查询都在数据库中,客户端应用程序也必须运行 EXECUTE PROCEDURE 语句。此处可能发生 SQL 注入,例如,如果您在其中插入一个应用程序变量作为过程名称。
      【解决方案5】:

      不,因为您仍然可以在存储过程中使用 D-SQL...并且在任何情况下验证和限制您的输入都是一个好主意。

      【讨论】:

        【解决方案6】:

        存储过程不是保证,因为实际上易受攻击的是任何动态代码,包括存储过程中的代码和动态生成的对存储过程的调用。

        只要不使用任意输入来生成代码,参数化查询和使用参数调用的存储过程都不会受到注入的影响。请注意,有很多动态代码也不易被注入(例如动态代码中的整数参数)。

        然而,很大程度上(我不确定 100% 是否真的有可能)存储基于 procs 的架构的好处是,对于客户端的动态代码,注入甚至可以在一定程度上得到防御(但不是完美的),因为:

        只有 EXEC 权限被授予应用程序连接的任何用户上下文,因此任何 SELECT、INSERT、UPDATE、DELETE 查询都将失败。当然,无论如何都不应该允许 DROP 等。因此,任何注入都必须采用 EXEC 的形式,因此最终,只有您在 SP 层中定义的操作才能被注入(而不是任意 SQL)。

        将数据库服务定义为一组存储过程(如软件中的任何抽象层)的许多其他好处包括在不影响应用程序的情况下重构底层数据库的能力,以及更好地理解和监控使用模式的能力使用分析器您的数据库,并且能够在数据库中选择性地优化而无需部署新客户端。

        【讨论】:

          【解决方案7】:

          此外,考虑使用细粒度的数据库访问,(通常也称为基于角色的访问控制)您的数据库的主要用户应该具有完成其工作所需的权限,而不是其他权限。安装后不需要创建新表吗?撤销该权限。没有以 sysdba 身份运行的合法需要?那就不要!如果用户没有被授予该权限,则指示用户“删除数据库”的偷偷摸摸的注入将被阻止。那么您只需要担心 SELECT 语句会泄露数据。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-06-26
            • 2018-10-06
            • 1970-01-01
            • 1970-01-01
            • 2010-10-12
            • 1970-01-01
            • 2016-10-15
            相关资源
            最近更新 更多