Reputation: 839
I get acquainted with QUOTENAME function. But I don't understand for what I can use it? Why it is so widely used?
select quotename('[abc]') -- '[[abc]]]'
select quotename('abc') -- '[abc]'
select '[' + 'abc' +']' -- why it is not so good as previous?
Upvotes: 3
Views: 3243
Reputation: 453628
Imagine the following script is scheduled to run regularly to clean up tables in schemas other than the dbo
schema.
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
If you create the following and run the script then all works as expected despite using the manual string concatenation approach. The table foo.bar
is dropped.
CREATE SCHEMA foo
CREATE TABLE foo.bar(x int)
Now create the following and try
CREATE TABLE foo.[[abc]]](x int)
The script fails with an error
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]'.
So not using QUOTENAME
has caused the script to fail. The closing bracket was not escaped properly by doubling it up. The correct syntax should have been
DROP TABLE [foo].[[abc]]]
Even worse news is that a malicious developer has come to know of the script's existence. They execute the following just before the script is scheduled to run.
CREATE TABLE [User supplied name]];
EXEC sp_addsrvrolemember 'SomeDomain\user2216', 'sysadmin'; --]
(
x int
)
Now the script that ends up being executed is
DROP TABLE [foo].[User supplied name];
EXEC sp_addsrvrolemember 'SomeDomain\user2216', 'sysadmin'; --]
The ]
was interpreted as closing off the object name and the remainder as a new statement. The first statement returned an error message but not a scope terminating one and the second one was still executed. By not using QUOTENAME
you have opened yourself up to SQL injection and the developer has successfully escalated their privileges
Upvotes: 7
Reputation: 3299
QUOTENAME
can be used when generating dynamic SQL statements. It'll indeed place your column name between brackets but will also escape characters which would break your quoted column name and could cause SQL injection.
For example:
SELECT QUOTENAME('abc[]def');
Will return:
[abc[]]def]
For more info: QUOTENAME (MSDN)
Upvotes: 1