Соединения на основе параметров не подвержены внедрению SQL - PullRequest
0 голосов
/ 28 ноября 2018

Я хочу сделать нестандартный запрос с объединением на основе параметров.

Например, у меня есть 2 таблицы: a_examples и b_examples оба с полями: field_x и field_y .Я хочу объединить строки, когда обе таблицы имеют одинаковые значения в field_x (или field_y ).

Пример запроса может выглядеть следующим образом:

AExample.joins('INNER JOIN b_examples ON b_examples.field_x = a_examples.field_x')

Проблема возникает, когда у меня есть имя поля на основе параметра.Например, у меня есть переменная field_name и я хочу использовать ее для запроса.Я могу сделать это так:

AExample.joins("INNER JOIN b_examples ON b_examples.#{field_name} = a_examples.#{field_name}")

Этот запрос работает, но подвержен внедрению SQL.

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

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Не пытайтесь сделать это: (пояснение ниже)

Вы можете использовать модуль ActiveRecord :: Sanitization и написать что-то вроде следующего, внутриваша модель ActiveRecord:

AExample.joins("INNER JOIN b_examples ON b_examples.#{sanitize_sql(field_name)} = a_examples.#{sanitize_sql(field_name)}")

Или вы можете включить модуль где-нибудь еще и использовать его там (например, ваш контроллер).

Используйте это вместо этого: (включено из другого ответа)

AExample.joins("INNER JOIN b_examples ON b_examples.#{ActiveRecord::Base.connection.quote_column_name(field_name)} = a_examples.#{ActiveRecord::Base.connection.quote_column_name(field_name)}")

Если столбец не будет найден, возникнет ошибка, которая не позволит вредоносному коду ввести ваш запрос.

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

case dynamic_field
when 'field_x'
 AExample.joins('INNER JOIN b_examples ON b_examples.field_x = a_examples.field_x')
when 'field_y'
 AExample.joins('INNER JOIN b_examples ON b_examples.field_y = a_examples.field_y')
else
  raise "Some suspicious parameter was sent!: #{dynamic_field}"
end

Или даже напишу scopes в вашей модели и не используйте этот код.летать

При таких проблемах, как, например, с шифрованием, попытайтесь найти обходной путь и по возможности избегайте реализации собственных решений.

РЕДАКТИРОВАТЬ:

Метод sanitize_sql предназначен для санации условий для предложения WHERE ( ActiveRecord :: Sanitization ):

Принимает массив или строку условий SQL и санирует их вдопустимый фрагмент SQL для предложения WHERE.

Это не вариант, так как вы пытаетесь выполнить санитарную обработку для условия INNER JOIN или ON.

Обратите внимание, что модуль ActiveRecord::Sanitization имеет опции только для WHERE, SET, ORDER и LIKE.Мне не удалось найти метод очистки для имени столбца, INNER JOIN или предложения ON.Возможно, это полезная функциональность, которую следует добавить в Rails в следующей версии.

Использование sanitize_sql со строкой передает ее почти без фильтрации, поэтому, если переменная field_name содержит некоторый вредоносный код в виде:

"field_x = a_examples.field_x; DROP TABLE a_examples; --"

Он будет включен в ваш запрос, без каких-либо ошибок. .

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

РЕДАКТИРОВАТЬ 2:

Добавлено рабочее решение для экранирования столбцаназвание.При вводе вредоносного кода возникает ошибка, поскольку столбец с таким именем не будет найден.

0 голосов
/ 28 ноября 2018

Вы можете очистить параметры, используя ActiveRecord::Base.connection.quote(string) или даже .quote_column

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...