#postgresql #sql-injection
#postgresql #sql-инъекция
Вопрос:
Я пытаюсь параметризовать свой запрос postgresql, чтобы предотвратить внедрение SQL в мое приложение ruby on rails. SQL-запрос будет суммировать разные значения в моей таблице в зависимости от входных данных.
Вот упрощенная версия моей функции:
def self.calculate_value(value)
calculated_value = ""
if value == "quantity"
calculated_value = "COALESCE(sum(amount), 0)"
elsif value == "retail"
calculated_value = "COALESCE(sum(amount * price), 0)"
elsif value == "wholesale"
calculated_value = "COALESCE(sum(amount * cost), 0)"
end
query = <<-SQL
select CAST(? AS DOUBLE PRECISION) as ? from table1
SQL
return Table1.find_by_sql([query, calculated_value, value])
end
Если я вызову calculate_value("retail")
, он выполнит запрос следующим образом:
select location, CAST('COALESCE(sum(amount * price), 0)' AS DOUBLE PRECISION) as 'retail' from table1 group by location
Это приводит к ошибке. Я хочу, чтобы он выполнялся без кавычек, подобных этому:
select location, CAST(COALESCE(sum(amount * price), 0) AS DOUBLE PRECISION) as retail from table1 group by location
Я понимаю, что добавление цитат — это то, что предотвращает sql-инъекцию, но как я могу предотвратить это в этом случае? Каков наилучший способ справиться с этим сценарием?
ПРИМЕЧАНИЕ: это упрощенная версия запросов, которые я буду писать, и я хочу использовать find_by_sql .
Комментарии:
1. Вам нужны двойные кавычки для идентификаторов, одинарные кавычки или значения.
2. Псевдоним не может быть параметром. Более того, он должен быть постоянным — динамическая структура вывода не является детерминированной. Рекомендация — создайте 3 отдельных окончательных непараметризованных текста запроса и выберите один из них в зависимости от предоставленного параметра.
Ответ №1:
Подготовленный оператор не может изменять структуру запроса: имена таблиц или столбцов, порядок предложений, имена функций и так далее. Таким образом можно изменять только литералы.
Где находится SQL-инъекция? Вы не собираетесь вводить пользовательское значение в текст запроса. Вместо этого вы проверяете заданное значение по списку разрешенных и используете только свои собственные написанные части SQL. В этом случае нет опасности SQL-инъекции.
Я также хочу дать ссылку на эту статью. Безопасно создавать текст запроса динамически, если вы управляете всеми частями этого запроса. И это намного лучше для СУБД, чем какая-то интеллектуальная логика в запросе.