SQL Server: правильное экранирование предложения Where в динамической процедуре (2)

#sql #sql-server #stored-procedures #dynamic #escaping

#sql #sql-сервер #хранимые процедуры #динамический #экранирование

Вопрос:

У меня есть динамическая процедура, в которой я хочу использовать приведенное ниже как часть моего предложения Where (все остальное работает по назначению).

В настоящее время это создает следующую ошибку: Incorrect syntax near the keyword 'LIKE'

 AND         CASE WHEN '   @searchCategory   ' <> ''dateRec'' THEN
                (R.'   @searchCategory   ' LIKE ''%'   @searchTerm   '%'')
                ELSE
                (R.dateRec = '   CONVERT(VARCHAR, @searchTerm, 111)   ')
                END
  

Как здесь будет выглядеть правильное экранирование?

Комментарии:

1. Пожалуйста, отправьте весь запрос целиком, вы удалили кавычки, и динамический sql инвертируется на нединамический.

2. Остальная часть процедуры работает и слишком длинная, чтобы публиковать ее здесь — речь идет только об этих строках.

3. ХОРОШО, все в порядке, это недопустимо CASE WHEN xxx <> 'dateRec' THEN (R.xxx LIKE '%yyy%') оператор THEN сообщает SQL, что использовать, и вы выполняете другое сравнение. Это не проблема, это проблема синтаксиса.

4. Хорошо, это возможно. У меня нет большого опыта работы с динамическими процедурами. Как бы мне написать это правильно?

5. Что именно вы пытаетесь сделать?

Ответ №1:

Я считаю, что это то, что вы ищете:

 declare @sql nvarchar(max), @searchCategory nvarchar(max), @searchTerm nvarchar(max)
set @searchCategory = 'dateRec'
set @searchTerm = 'yyy'

set @sql = 
'AND (
       ('''   @searchCategory   ''' <> ''dateRec'' AND (R.'   @searchCategory   ' LIKE ''%'   @searchTerm   '%''))
       OR
       ('''   @searchCategory   ''' = ''dateRec'' AND (R.dateRec = '''   CONVERT(VARCHAR, @searchTerm, 111)   '''))
     )'
print @sql
  

Комментарии:

1. Это здорово — большое спасибо! Что в итоге делает печать? В настоящее время я завершаю свою процедуру с помощью EXEC(@sql).

2. Это встраивает текст @searchTerm в произвольной форме в SQL. Это открывает вам путь к атаке с использованием SQL-инъекций LittleBobbyTables. Вместо использования EXEC этого shoudl используйте sp_executesql и, таким образом, сможете передавать параметры в dynamic-sql. Таким образом @searchCategory , требуется только подстановка в sql-строку, и это можно проверить в белом списке, чтобы убедиться, что это не атака.

3. @MatBailie: Спасибо за это !

Ответ №2:

Предполагая, что содержимое @searchCategory фактически не содержит символов '

 SET @sql = 'AND '  
           CASE WHEN @searchCategory <> 'dateRec' THEN
             '(R.'   @searchCategory   ' LIKE ''%''   @searchTerm   ''%'')'
           ELSE
             '(R.dateRec = CONVERT(VARCHAR, @searchTerm, 111))'
           END
  

Это даст либо….

 AND (R.foobar LIKE '%'   @searchTerm   '%')
  

или…

 AND (R.dateRec = CONVERT(VARCHAR, @searchTerm, 111))
  

Это означает, что вы все равно будете передавать @searchTerm в sp_executesql качестве параметра, чтобы защитить вас от атак SQL-инъекций.

Вы НЕ хотите напрямую вставлять текст произвольной формы пользователя в свой SQL. Текст в произвольной форме должен оставаться в качестве параметра, чтобы закрыть эту дыру в безопасности.

(Я также предполагаю, что у вас есть белый список допустимых значений @searchCategory , чтобы предотвратить злоупотребление этим с помощью SQL-инъекционной атаки?.)

Редактировать :

Пример динамического sql, который поддерживает параметризацию….

 DECLARE @SQL nvarchar(500);

SET @SQLString = N'SELECT * FROM table WHERE '   @param1   ' = @param;';

EXECUTE sp_executesql
   @SQL,
   '@param NVARCHAR(500)',
   @param2
  

Используя этот метод, вам нужно проверить, что @param1 действительно является допустимым именем поля, например, используя белый список, но вам не нужно проверять @param2. Это связано с тем, что @param2 передается sp_executesql как сам параметр. Это похоже на динамическое создание хранимой процедуры с параметрами, а не на встраивание всех ваших значений в строку sql, что делает вас открытыми для серьезных атак sql-инъекций.

Редактировать :

Это не тот случай, когда оператор встраивается в LIKE CASE оператор. Что здесь делается, так это создание строки, которая создает строковый литерал LIKE , с помощью оператора CASE .

Это почти то же самое, что и это…

 SET @sql = 'AND '  
           CASE WHEN @searchCategory <> 'dateRec' THEN
             'A string with the word'   ' LIKE '   'in it'
           ELSE
             'A different string without that word in it'
           END
  

Комментарии:

1. @JiggsJedi — Это не то, что вы думаете. это LIKE просто фрагмент текста (строковый литерал), а не команда. Это оператор case создает строку SQL, где строка SQL содержит текст LIKE . Это не оператор case с оператором LIKE внутри него.

2. @JiggsJedi — я не говорю, что это вообще допустимо. Вы правы, что ваш пример верен. То, что я написал, не соответствует вашему примеру. Я обновлю свой ответ, чтобы сделать его более понятным.

3. @MatBailie: Спасибо за это — это все еще очень полезно!

4. Я отказываюсь от своих комментариев. Клянусь вам, ДЕЛО было в » когда я впервые посмотрел. Вы правы, сэр.