Динамический SQL — поисковый запрос — переменное количество ключевых слов

Мы пытаемся обновить нашу классическую поисковую систему asp, чтобы защитить ее от SQL-инъекций. У нас есть функция VB 6, которая динамически строит запрос, объединяя запросы вместе на основе различных параметров поиска. Мы преобразовали это в хранимую процедуру, используя динамический sql для всех параметров, кроме ключевых слов.

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

Пример:

@CustomerId AS INT
@Keywords AS NVARCHAR(MAX)

@sql = 'SELECT event_name FROM calendar WHERE customer_id = @CustomerId '

--(loop through each keyword passed in and concatenate)

@sql = @sql + 'AND (event_name LIKE ''%' + @Keywords + '%'' OR event_details LIKE ''%' + @Keywords + '%'')'

EXEC sp_executesql @sql N'@CustomerId INT, @CustomerId = @CustomerId

Каков наилучший способ справиться с этим и обеспечить защиту от SQL-инъекций?


person Chad Monahan    schedule 30.09.2008    source источник


Ответы (4)


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

Пример:

string sql  = "SELECT Name, Title FROM Staff WHERE UserName=@UserId";
using (SqlCommand cmd = new SqlCommand(sql))
{
  cmd.Parameters.Add("@UserId", SqlType.VarChar).Value = "smithj";

Вы можете построить строку SQL в зависимости от набора столбцов, которые вам нужно запросить, а затем добавить значения параметров после завершения строки. Это немного сложно сделать, но я думаю, что это намного проще, чем иметь действительно сложный TSQL, который раскрывает множество возможных перестановок возможных входных данных.

person Rikalous    schedule 30.09.2008

У вас есть 3 варианта здесь.

  1. Используйте функцию, которая преобразует таблицы списков, и присоединитесь к ней. Так что у вас будет что-то вроде этого.

    SELECT * 
    FROM calendar c
       JOIN dbo.fnListToTable(@Keywords) k 
           ON c.keyword = k.keyword  
    
  2. Иметь фиксированный набор параметров и разрешать поиск не более N ключевых слов.

    CREATE PROC spTest
    @Keyword1 varchar(100),
    @Keyword2 varchar(100),
    .... 
    
  3. Напишите функцию экранирования строк в TSQL и экранируйте свои ключевые слова.

person Sam Saffron    schedule 30.09.2008

  • Если вам это не нужно, вы можете просто удалить любой символ, которого нет в [a-zA-Z ] - большинство этих вещей не будет в поиске, и вы не сможете быть введены таким образом, и вам не нужно беспокоиться о ключевых словах или что-то в этом роде. Однако, если вы разрешаете кавычки, вам нужно быть более осторожным.

  • Подобно sambo99 # 1, вы можете вставить ключевые слова во временную таблицу или переменную таблицы и присоединиться к ней (даже с использованием подстановочных знаков) без опасности внедрения:

Это не очень динамично:

SELECT DISTINCT event_name
FROM calendar
INNER JOIN #keywords
    ON event_name LIKE '%' + #keywords.keyword + '%'
    OR event_description LIKE '%' + #keywords.keyword + '%'
  • Фактически вы можете сгенерировать SP с большим количеством параметров вместо того, чтобы кодировать его вручную (установите значения по умолчанию на '' или NULL в зависимости от ваших предпочтений при кодировании ваших поисков). Если вы обнаружите, что вам нужно больше параметров, было бы просто увеличить количество генерируемых параметров.

  • Вы можете переместить поиск в полнотекстовый индекс вне базы данных, такой как Lucene, а затем использовать результаты Lucene для извлечения совпадающих строк базы данных.

person Cade Roux    schedule 01.10.2008

Вы можете попробовать это:

SELECT * FROM [tablename] WHERE LIKE % +keyword%
person Ajascopee    schedule 17.10.2010