为什么我们应该使用QUOTENAME功能?

use*_*216 3 t-sql sql-server

我熟悉QUOTENAME功能.但我不明白我能用什么呢?为什么这么广泛使用?

select quotename('[abc]') -- '[[abc]]]'
select quotename('abc') -- '[abc]'
select '[' + 'abc' +']'  -- why it is not so good as previous?
Run Code Online (Sandbox Code Playgroud)

Mar*_*ith 6

想象一下,计划定期运行以下脚本来清理模式以外的dbo模式中的表.

DECLARE @TABLE_SCHEMA SYSNAME,
        @TABLE_NAME   SYSNAME
DECLARE @C1 AS CURSOR;

SET @C1 = CURSOR FAST_FORWARD
FOR SELECT TABLE_SCHEMA,
           TABLE_NAME
    FROM   INFORMATION_SCHEMA.TABLES
    WHERE  TABLE_SCHEMA <> 'dbo'

OPEN @C1;

FETCH NEXT FROM @C1 INTO @TABLE_SCHEMA, @TABLE_NAME;

WHILE @@FETCH_STATUS = 0
  BEGIN
      PRINT 'DROP TABLE [' + @TABLE_SCHEMA + '].[' + @TABLE_NAME + ']';

      EXEC ('DROP TABLE [' + @TABLE_SCHEMA + '].[' + @TABLE_NAME + ']');

      FETCH NEXT FROM @C1 INTO @TABLE_SCHEMA, @TABLE_NAME;
  END 
Run Code Online (Sandbox Code Playgroud)

如果您创建以下内容并运行脚本,则尽管使用手动字符串连接方法,但所有操作都按预期工作.该表foo.bar已删除.

CREATE SCHEMA foo
CREATE TABLE foo.bar(x int)
Run Code Online (Sandbox Code Playgroud)

现在创建以下内容并尝试

CREATE TABLE foo.[[abc]]](x int)
Run Code Online (Sandbox Code Playgroud)

该脚本失败并显示错误

DROP TABLE [foo].[[abc]]
Msg 105, Level 15, State 1, Line 6
Unclosed quotation mark after the character string '[abc]'.
Msg 102, Level 15, State 1, Line 6
Incorrect syntax near '[abc]'.
Run Code Online (Sandbox Code Playgroud)

所以不使用QUOTENAME导致脚本失败.关闭括号没有通过加倍来正确逃脱.应该是正确的语法

DROP TABLE [foo].[[abc]]]
Run Code Online (Sandbox Code Playgroud)

更糟糕的是,恶意开发者已经了解了脚本的存在.它们在脚本计划运行之前执行以下操作.

CREATE TABLE [User supplied name]]; 
EXEC sp_addsrvrolemember 'SomeDomain\user2216', 'sysadmin';  --]
(
x int
)
Run Code Online (Sandbox Code Playgroud)

现在最终执行的脚本是

DROP TABLE [foo].[User supplied name]; 
EXEC sp_addsrvrolemember 'SomeDomain\user2216', 'sysadmin';  --]
Run Code Online (Sandbox Code Playgroud)

]被解读为封闭的对象名,其余为新的声明.第一个语句返回一条错误消息,但没有一个范围终止一个,第二个语句仍然执行.通过不使用,QUOTENAME您已经打开了自己的SQL注入,开发人员已经成功升级了他们的权限