flawopen.com/SQL Injection в Ruby/ActiveRecord where()
Безопасна ли интерполяция в Rails where()?
Представьте SQL как бланк с неизменными инструкциями и пустыми полями для значений. Связанный параметр заполняет поле; интерполяция Ruby вставляет текст запроса в инструкции до того, как Rails сможет разделить эти части. Оставляйте структуру SQL неизменной и передавайте недоверенные значения как параметры.
User.where(
"id = #{params[:id]}"
)
User.where(id: params[:id])
# or, for more complex conditions:
User.where("id = ?", params[:id])
Почему интерполяция меняет запрос
Ruby вычисляет #{...} до того, как Active Record получает условие. Например, where("id = #{params[:id]}") передаёт Rails уже объединённую SQL-строку, поэтому данные запроса могут изменить предикат. Active Record указывает, что такой способ сборки строки небезопасен. Используйте hash для поддерживаемых условий равенства, диапазона или подмножества либо маркеры ? для других предикатов. Маркеры связывают значения, но не имена объектов и не ключевые слова SQL; фиксируйте структуру запроса или выбирайте идентификаторы из строгого списка разрешённых значений.
Как проверить код
rg -n 'where\s*\(' app/Частые вопросы
Нет. Hash-условия Rails поддерживают равенство, диапазон и подмножество (IN). Для других предикатов используйте фиксированное SQL-условие со связанными значениями, например where("price > ?", amount). Связывание защищает значения, но не динамические имена таблиц и столбцов или SQL-фрагменты.