Представьте себе следующий сценарий планируется регулярно запускать для очистки таблиц, отличных от 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-инъекцию, и разработчик успешно обострил свои права.
Не могли бы вы дать более подробную информацию о том, как это предотвращает инъекции? – user2216
Если вы используете QUOTENAME вокруг строк ввода пользователя, подобные вещи не являются проблемой. выберите QUOTENAME ('или 1 = 1; пользователи обрезанных таблиц) –
@ user2216 - добавлен пример –