Какая функция заключает в кавычки идентификатор в динамическом sql с SQL Server?

11

Что такое метод безопасного цитирования идентификаторов SQL Server для динамического создания SQL?

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

Допустим, у меня есть оператор SQL,

SELECT [$col] FROM table;

который по сути такой же, как

'SELECT [' + $col + '] FROM table;'

Что останавливает инъекционную атаку, где

$col = "name] FROM sys.objects; \r\n DROP TABLE my.accounts; \r\n\ --";

В результате чего

SELECT [name] FROM sys.objects;
DROP TABLE my.accounts;
-- ] FROM table;
Эван Кэрролл
источник

Ответы:

14

Функция, которую вы ищете, это QUOTENAME!

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

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

Хороший код

DECLARE @sql NVARCHAR(MAX) = N''
SELECT @sql = 'SELECT ' + QUOTENAME(d.name) + ' FROM your_mom'
FROM sys.databases AS d

Плохой код

DECLARE @sql NVARCHAR(MAX) = N''
SELECT @sql = 'SELECT [' + d.name + '] FROM your_mom'
FROM sys.databases AS d

Чтобы привести конкретный пример ...

Следующее отлично работает для начального ввода

DECLARE @ObjectName SYSNAME = 'sysobjects';

DECLARE @dynSql NVARCHAR(MAX) = 'SELECT COUNT(*) FROM [' + @ObjectName + ']';

EXEC (@dynSql);

Но со злонамеренным вводом это уязвимо для инъекции SQL

DECLARE @ObjectName SYSNAME = 'sysobjects];SELECT ''This is some arbitrary code executed. It might have dropped a table or granted permissions''--'

DECLARE @dynSql NVARCHAR(MAX) = 'SELECT  COUNT(*)  FROM [' + @ObjectName + ']';

EXEC (@dynSql);

QUOTENAMEПравильное использование экранирует встроенное ]и предотвращает попытки внедрения SQL.

DECLARE @ObjectName SYSNAME = 'sysobjects];SELECT ''This is some arbitrary code executed. It might have dropped a table or granted permissions''--'

DECLARE @dynSql NVARCHAR(MAX) = 'SELECT  COUNT(*)  FROM ' + QUOTENAME(@ObjectName);

EXEC (@dynSql);

Неверное имя объекта 'sysobjects]; SELECT' Это какой-то произвольный исполняемый код. Возможно, он отбросил таблицу или получил разрешения «-».

Эрик Дарлинг
источник