【问题标题】:Is sql injection possible in stored procedures with text param?在带有文本参数的存储过程中是否可以进行 sql 注入?
【发布时间】:2012-10-08 19:49:06
【问题描述】:

我在我的存储过程中使用这样的查询

SET @Statement =
'SELECT Id,Title,Content,Status,ROW_NUMBER()
        OVER (ORDER BY ' + @Sort + ') AS StudentReport

         FROM YearBook

        WHERE ' + @Criteria + ')

         AS ArticleNumber

        WHERE StudentReport> ' + CONVERT(NVARCHAR, @StartRowIndex) + ' AND

        StudentReport<= (' + CONVERT(NVARCHAR, @StartRowIndex + @MaximumRows);

只想知道是否可以对这个存储过程进行sql注入。如果是,我该如何预防?需要帮助!!!

【问题讨论】:

  • 那是有效的 TSQL 吗?您能否展示一个代表您关注的 SP 的精简但有效的示例?
  • 我已经编辑了你的问题,这是你的意思吗?如果是这样,您的 SP 如何执行该 SQL? @Sort@Criteria 参数是否属于 SP?
  • 一般来说,如果您接受 varchars 并将它们视为 sql 块,那么您有一个好处和两个问题。您的 SP 将非常灵活,因为您的 SP 很灵活,很难为它制定一致的有用查询计划,为什么要有一个 SP,因为它非常灵活,我可以用它来做您可能不打算做的事情,那将是注入攻击。
  • 那么,您的 SP 是如何执行动态创建的查询的呢?
  • 使用 C# 代码,我正在运行 SP

标签: c# sql sql-server


【解决方案1】:

是的,这是可能的。很容易,甚至。尝试设置

@Criteria = "\r\nGO\r\nexec sp_addlogin 'hacker', 'broken'\r\nGO";

批次会产生错误,但中间的部分仍然会运行,所以欢迎您的新登录。


进行查询的正确方法可能是这样的。
CREATE PROC FindSomething
  @StartRowIndex int,
  @MaximumRows int,
  @Sort int, -- 1-4 representing the columns, say in a dropdown
  @Id int,
  @Content varchar(max),
  @Title varchar(max),
  @Status int
AS
SELECT Id,Title,Content,Status
FROM
(
    SELECT Id,Title,Content,Status,
           ROW_NUMBER() OVER (ORDER BY
               CASE when @Sort = 1 then Id
                    when @Sort = 4 then Status
                    end,
               CASE when @sort = 2 then Title
                    when @sort = 3 then Content
                    end) AS StudentReport
    FROM YearBook
    WHERE (@id is null or @id = Id)
      AND (@Content is null or @Content = Content)
      AND (@Title is null or @Title = Title)
      AND (@status is null or @Status = Status)
) Numbered
WHERE StudentReport >= @StartRowIndex
  AND StudentReport <= @StartRowIndex + @MaximumRows
OPTION (RECOMPILE);
GO

在此处阅读有关动态搜索的更多信息:www.sommarskog.se/dyn-search.html

注意:我在排序中将 1/4 和 2/3 分开,因为 CASE 语句的每个分支都必须产生相同的类型,或者是兼容的。 int/varchar 在 case 语句中是非常糟糕的组合。

【讨论】:

  • 有没有办法向存储过程提供诸如 group = 'b' 或类似这样的条件?我的意思是设置一个表达式验证器并阻止它?
  • 我不太了解...请忽略我的错误
  • 这是否意味着,代替Content占位符,即使我们传递一个查询,它也只会被视为文本,而不是查询?
  • 如果您有不同的 where 子句创建不同的存储过程,这是一个很好的仅 TSQL 方法。 +1
  • 整个就是一个存储过程。您只向它传递参数,而不是进行临时查询。 sql注入概率为0.00%。
【解决方案2】:

假设上面是你正在构建的字符串,然后用EXECsp_executesql执行然后,SQL注入是可能的。

如何防止它取决于您要执行的操作。也许您需要重新考虑您的方法。

【讨论】:

    【解决方案3】:

    是的,它会的。你仍然可以做一些事情来帮助防御它'

    例如,@Sort 是一个列名,因此您可以正确地对其进行转义(并确保如果有人试图将某些东西注入其中,它不会起作用,因为它已被正确转义。为此使用 @987654321 @。

    QUOTENAME(@Sort)
    

    @Criteria 更加困难,因为您实际上期望的是 SQL 代码片段,因此很难确定什么是有效的,什么是恶意的。您可能想重新考虑您在这里尝试做什么。如果您必须使用 Criteria,请确保设置了安全模型,以便只有绝对需要它的应用程序才能访问执行此操作的存储过程。确保在发送 SQL 之前在应用程序中进行验证,以确保它所做的任何事情都不会造成破坏。

    【讨论】:

      【解决方案4】:

      看起来您正在尝试使用分页创建一个非常通用的搜索存储过程。这些很难仅在 t-sql 中正确实现,并且由于分支逻辑或您需要添加的其他支持存储过程,可能会成为维护方面的难题......

      我将开始研究纯 sql 方法之外的其他选项。使用 orm 或 micro orm 会有很大帮助。实际上,看看 Sam Saffron 想出了什么......

      http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-20
        • 2020-05-28
        • 2018-01-16
        • 1970-01-01
        • 2012-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多