2016-10-07 32 views

回答

5

想象一下,定期运行以下脚本以清除除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 

如果您创建以下并运行该脚本,则尽管使用手动字符串连接方法,但仍然按预期工作。表foo.bar被删除。

CREATE SCHEMA foo 
CREATE TABLE foo.bar(x int) 

现在创建以下,并尝试

CREATE TABLE foo.[[abc]]](x int) 

脚本失败

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]'. 

所以不使用QUOTENAME已引起脚本失败的错误。将右括号加倍不能正确逃脱。正确的语法应该是

DROP TABLE [foo].[[abc]]] 

更糟糕的消息是恶意开发者已经知道脚本的存在。它们在脚本计划运行之前执行以下操作。

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

现在正在执行的最终剧本

DROP TABLE [foo].[User supplied name]; 
EXEC sp_addsrvrolemember 'SomeDomain\user2216', 'sysadmin'; --] 

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

+0

请您提供有关如何防止注入更多的细节? – user2216

+0

如果你在用户输入字符串周围使用QUOTENAME,这样的事情不是问题。选择QUOTENAME('或1 = 1; truncate table Users') –

+0

@ user2216 - 添加示例 –

1

QUOTENAME可以在生成动态SQL语句时使用。它确实会将您的列名置于括号之间,但也会转义会破坏您引用的列名称并可能导致SQL注入的字符。

例如:

SELECT QUOTENAME('abc[]def'); 

返回结果:

[abc[]]def] 

欲了解更多信息:QUOTENAME (MSDN)

相关问题