我熟悉QUOTENAME功能。但我不明白我能用什么呢?为何如此广泛使用?
select quotename('[abc]') -- '[[abc]]]'
select quotename('abc') -- '[abc]'
select '[' + 'abc' +']' -- why it is not so good as previous?
答案 0 :(得分: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
如果您创建以下内容并运行脚本,则尽管使用手动字符串连接方法,但所有内容都按预期工作。表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注入,并且开发人员已成功升级其权限
答案 1 :(得分:1)
QUOTENAME
。它确实会将您的列名放在括号之间,但也会转义会破坏您引用的列名并可能导致SQL注入的字符。
例如:
SELECT QUOTENAME('abc[]def');
将返回:
[abc[]]def]
了解更多信息:QUOTENAME (MSDN)