Должны ли мы по-прежнему использовать QUOTENAME для защиты от инъекционных атак?

9

Сегодня я просматривал старую хранимую процедуру и заметил, что она использует quotenameвходные параметры. После некоторых копаний, чтобы выяснить, что это делает, я наткнулся на этот сайт . Теперь я понимаю, что он делает и как его использовать, но на сайте написано, что он используется для предотвращения атак SQL-инъекций. Когда я использовал для разработки приложений, которые напрямую запрашивали базу данных, используя asp.net, я использовал параметры ADO.Net для передачи пользовательского ввода в виде буквального значения и никогда не беспокоился о его защите в моих хранимых процедурах.

Сейчас я пишу хранимую процедуру, которая будет использоваться приложениями, которые я не пишу, поэтому мне нужно попытаться защитить ее от атак с использованием инъекций на уровне процедуры, это quotenameлучший способ сделать это или есть более новая функция / лучше метод?

Код, который заставил меня задуматься над этим ( @parm1это пользовательский параметр ввода):

'SELECT project [Project], project_desc [Description], 
        customer [Customer], cpnyid [Company]
FROM PJPROJ (nolock)
where project like ' + quotename(@parm1,'''') + '
Мэтью Верстраете
источник

Ответы:

17

Да, в этой области многое не изменилось, вы должны использовать quotenameлюбые имена объектов сервера SQL, которые используются в динамическом SQL (особенно, если они предоставляются внешним образом в ваш код). Помимо смягчения SQL-инъекций это также означает, что ваш код будет работать правильно для нестандартных имен идентификаторов.

Функция подходит только для имен объектов (например, таблицы, столбца, базы данных).

Вы должны попытаться параметризировать все остальное и использовать sp_executesql, передавая параметры, а не объединяя их в строку запроса.

Окончательная статья на эту тему - «Проклятие и благословения динамического SQL».


Редактировать. Теперь вы предоставили код, который, как я вижу, передает второй параметр, 'чтобы добавить внешние кавычки и экранировать любые одиночные кавычки, удваивая их, прежде чем вводить их в строку. Это не очень хорошее использование quotename. Он потерпит неудачу (вернет ноль), если длина строки превышает 128 символов.

Кроме того, он может по-прежнему оставлять возможности SQL-инъекции, если строка содержит U + 02BC вместо стандартного апострофа, а затем строка назначается varchar после очистки ( где она может быть автоматически преобразована в обычный апостроф )

Правильный способ сделать это - оставить параметризованный запрос. А затем передать @parm1значение вsys.sp_executesql

DECLARE @Sql NVARCHAR(MAX);

SET @Sql = '
SELECT project      [Project],
       project_desc [Description],
       customer     [Customer],
       cpnyid       [Company]
FROM   PJPROJ (nolock)
WHERE  project LIKE @parm1 
';

EXEC sys.sp_executesql
  @Sql,
  N'@parm1 varchar(100)',
  @parm1 = 'foobar%'; 
Мартин Смит
источник