【问题标题】:How execute a dynamic query in stored procedure?如何在存储过程中执行动态查询?
【发布时间】:2020-04-04 00:48:08
【问题描述】:

我想从用户变量中获取:'Top' 子句的 num 和来自 northwind DB 的 Tbl 名称, 为了取回前 5 名的结果集,我的脚本已关闭

create procedure sp_getTop5 
(
    @num int , 
    @tbl nvarchar(max)
)    
as       
    declare @res nvarchar(max);       
    set @res =  'select top '+str(@num)+' *   from '+@tbl

    exec @res   

---- check
exec sp_getTop5 5, employees

【问题讨论】:

  • 太棒了。有什么问题?
  • 天哪!!!这只是一个等待发生的注入问题。为什么要将未经处理的 nvarchar(MAX) 注入到 EXEC 语句中?!
  • 没有 ORDER BY 的 Top N 也可能产生意想不到的结果

标签: sql sql-server stored-procedures dynamic-sql


【解决方案1】:

哇...除了这是我见过的最可怕的动态陈述之一,我没有什么可以说的了。您实际上是在让恶意人员访问价值 2GB 的字符来注入(这是 1,073,741,824 个字符,nvarchar(MAX))反对很容易遭受注入的语句。他们将字面上能够在足够的时间(和权限)下做任何他们想做的事情。请花点时间阅读我在Dos and Don'ts of Dynamic SQL 上的文章并查看Little Bobby Tables 以了解您拥有的东西有多危险。

至于您的 SQL,我不在乎您没有真正提出问题,您现在需要修复安全模型中的那个巨大漏洞:

CREATE PROC getTop5 @Num int, @schema sysname, @table sysname AS --Removed sp_ prefix, see after the answer
BEGIN
    DECLARE @SQL nvarchar(MAX);
    SELECT @SQL = N'SELECT TOP (@Num) FROM ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + N';'
    FROM sys.schemas s
         JOIN sys.tables t ON s.schema_id = t.schema_id
    WHERE s.[name] = @schema
      AND t.[name] = @table;

    EXEC sp_executesql @SQL, N'@Num int', @Num;
END;
GO

然后你可以如下执行:

EXEC dbo.getTop5 5, N'dbo', N'YourTable';

这将(正如评论者刚刚提醒我的那样)从表中提供 N 行任意行(不是“顶部”行,并且表没有内置顺序)。因此,没有ORDER BY 的TOP 意味着在运行查询时每次返回的行可能不同。

至于我对前缀的评论:Is the sp_ prefix still a no-no?

【讨论】:

    猜你喜欢
    • 2012-09-04
    • 1970-01-01
    • 2013-01-08
    • 2012-12-26
    • 2021-12-13
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 2019-04-08
    相关资源
    最近更新 更多