我是否需要担心针对其主数据集使用存储过程的SSRS报告的SQL注入?

时间:2018-05-14 16:46:10

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

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

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

但是,我担心有人可能会输入一些恶意文本来试图破坏我的数据库。考虑到我使用的是SQL Server 2008 R2和SyteLine 8,我是否需要担心这个问题?或者已经有了保护措施,我不应该担心吗?

3 个答案:

答案 0 :(得分:1)

你正在考虑这件事,这很好。有一些方法可以设计报告,使其更容易受到SQL注入攻击。例如,如果您使用动态SQL并将参数值直接附加到查询中。

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

答案 1 :(得分:1)

简短回答:

YES

您始终必须使用安全编码实践来避免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;

答案 2 :(得分: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中构建值是安全的。我这样做的唯一一次是我有固定的硬编码值。就像我可以构建说"其中type = 1"或者它可能会说"其中type = 2",1和2是硬编码的,就像程序中的那样,而不是用户输入。如有疑问,请创建参数。