FlawOpen

flawopen.com/SQL Injection в Ruby/ActiveRecord where()

Безопасна ли интерполяция в Rails where()?

Справочная страница
Краткий ответ

Представьте SQL как бланк с неизменными инструкциями и пустыми полями для значений. Связанный параметр заполняет поле; интерполяция Ruby вставляет текст запроса в инструкции до того, как Rails сможет разделить эти части. Оставляйте структуру SQL неизменной и передавайте недоверенные значения как параметры.

UNSAFE
User.where(
  "id = #{params[:id]}"
)
SAFE
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/
Проверьте совпадения на интерполяцию или конкатенацию данных запроса внутри строк условий. Brakeman сообщает о рисках SQL Injection, когда анализ обнаруживает небезопасный поток данных; отсутствие предупреждений не доказывает безопасность всех запросов.

Частые вопросы

Можно ли использовать hash-условия для любого запроса?

Нет. Hash-условия Rails поддерживают равенство, диапазон и подмножество (IN). Для других предикатов используйте фиксированное SQL-условие со связанными значениями, например where("price > ?", amount). Связывание защищает значения, но не динамические имена таблиц и столбцов или SQL-фрагменты.

Источники

См. также SQL-инъекции (CWE-89): как они работают и как их предотвратить в любом языке — flawopen.com Защищает ли Sequelize query() от SQL-инъекций? Защищает ли SQLAlchemy text() от SQL-инъекций? Предотвращает ли проверка sqlx при компиляции SQL-инъекции? Защищают ли хранимые процедуры от SQL-инъекций? Защищает ли TypeORM QueryBuilder от SQL-инъекций? Django ORM и SQL Injection: безопасные шаблоны