【问题标题】:Do I need to worry about a SQL injection for an SSRS report that uses a stored procedure for its main dataset?我是否需要担心对主数据集使用存储过程的 SSRS 报告的 SQL 注入?
【发布时间】:2018-10-24 09:45:26
【问题描述】:

我有一份报告,我想添加一个单值文本参数(允许空值)。此参数将传递给存储过程。如果此参数为空,SP 将忽略它。但是,如果参数不为空,那么我希望 SP 解析它并使用其中包含的一些值。

用户将以whse=Blah&whse=Blah2&item=item1&lot=lotA&date:IsNull=True&um=&client=client2 的形式传递值。您可能会猜到,这些是报表的参数名称和值。我的想法是允许用户以这种形式传递他们想要的一些参数值。

但是,我担心有人会输入一些恶意文本来试图破坏我的数据库。鉴于我使用的是 SQL Server 2008 R2 和 SyteLine 8,我是否需要为此担心?还是已经为此提供了保护措施,我不必担心?

【问题讨论】:

  • 应包含您的代码(PHP 或其他)以使其更易于理解。但简单的回答是,是的,您应该始终小心 SQLi 以及使用未经处理的查询的后果。

标签: database reporting-services sql-server-2008-r2 sql-injection


【解决方案1】:

你是如何解析它的,你对结果做了什么?

如果您编写构建 SQL 语句的代码,那么您很容易受到 SQL 注入的攻击。

假设你这样写:

set @myquery = 'select customer_name from customer where customer_id = ''' + @custid + ''''
execute (@myquery)

假设您最终从用户输入获得@custid,比如表单上的文本框。

如果用户进入

42

那么查询就变成了

select customer_name from customer where customer_id = '42'

酷。大概这就是你想要的。

但假设用户输入

42'; update customer set balance_due = 0 where customer_id = '42

现在你的查询变成了

select customer_name from customer where customer_id = '42'; update customer set balance_due = 0 where customer_id = '42'

并且客户刚刚将应付余额归零。或者他可能会删除整个表等。

故事的寓意是,永远不要使用用户输入动态构建 SQL 查询。它使用户能够对您的数据库执行任何他们想做的事情。

正确的做法是:

select customer_name from customer where customer_id = @custid

然后,如果用户尝试使用 SQL 注入,他们只会在记录上创建一个 not-found,因为他们输入的 SQL 字符串不是有效的客户 ID。 (或者如果你不做任何类型检查,他们可能会得到一个数据转换错误。这也很糟糕,你应该防止这种情况,但不如 SQL 注入那么糟糕。)

避免动态构建 SQL 语句。尽可能将值作为参数传入。

好的,有时您只需要动态构建语句。我能想到的最常见的情况是一个选择标准屏幕,用户可以在其中输入 10 个不同标准的值——日期在这个范围内,名称包含这个,数量小于那个等等——但每个条件都是可选的,如果用户没有输入值,那么您不希望将该测试作为查询的一部分。因此,有数百万种可能的组合,您希望即时将查询组合在一起。这很好,但不要在动态构建查询时插入值。插入参数,然后设置参数。

如果值是在程序中生成而不是从用户输入中生成的,并且您绝对确定这些值永远不会包含 SQL 注入文本,那么将值构建到 SQL 中是安全的。我这样做的唯一一次是当我有固定的硬编码值时。就像我可能构建的代码说“类型 = 1”或者它可能说“类型 = 2”,并且 1 和 2 在程序中是硬编码的,而不是用户输入。如有疑问,请创建参数。

【讨论】:

    【解决方案2】:

    简答:

    是的

    您始终必须使用安全的编码实践来避免 SQL 注入漏洞。

    没有任何语言、框架或 RDBMS 产品可以阻止 SQL 注入。或者,考虑另一种方式,您总是有机会编写不安全的代码,尽管存在允许您编写安全代码的功能。

    SQL 注入防御是开发人员的责任,没有遵循安全的编码习惯和使用帮助您防御 SQL 注入的功能将是您的错。

    存储过程本身并不能保证输入数据的安全。

    如果您在动态 SQL 语句中使用输入数据,则应尽可能使用sp_executesql() 将动态部分变为参数。那是安全的。

    这是来自https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql?view=sql-server-2017的示例

    EXECUTE sp_executesql   
              N'SELECT * FROM AdventureWorks2012.HumanResources.Employee   
              WHERE BusinessEntityID = @level',  
              N'@level tinyint',  
              @level = 109;  
    

    使用查询参数。不要只是将变量连接到 SQL 字符串中。

    例如,以下内容是不安全的,因为@inBusEntityId 可能包含一些内容,使您的查询执行您不期望的事情:

    EXECUTE sp_executesql   
              N'SELECT * FROM AdventureWorks2012.HumanResources.Employee   
              WHERE BusinessEntityID = ' + @inBusEntityId;
    

    【讨论】:

      【解决方案3】:

      很高兴您考虑到这一点。您可以通过多种方式设计报表,使其更容易受到 SQL 注入的攻击。例如,如果您使用动态 SQL 并将参数值直接附加到查询中。

      但是,使用内置参数功能,这不是问题。当您将这些值传递给存储过程时,这些值将被参数化。如果该值因任何原因无效,它甚至不会尝试运行查询文本。换句话说,您不必考虑人们输入无效字符串的所有不同方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-18
        • 2019-04-10
        相关资源
        最近更新 更多