2016-10-07 2 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; пользователи обрезанных таблиц) –

+0

@ user2216 - добавлен пример –

1

QUOTENAME может использоваться при создании динамических операторов SQL. Он действительно разместит ваше имя столбца между скобками, но также позволит избежать символов, которые могут сломать ваше цитированное имя столбца и могут вызвать SQL-инъекцию.

Например:

SELECT QUOTENAME('abc[]def'); 

Вернет:

[abc[]]def] 

Для получения дополнительной информации: QUOTENAME (MSDN)

Смежные вопросы