Подтвердить что ты не робот

Лучший способ сделать санирующий вход пользователя в рельсы

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

before_validation :sanitize_content, :on => :create
def sanitize_content
  self.content = ActionController::Base.helpers.sanitize(self.content)
end

Нужно ли запускать это в каждом поле в каждой модели? Я угадываю: on = > : create тоже нужно удалить, так что он запускается и при обновлениях?

Другой вариант - дезинформировать, когда данные отображаются в представлениях, используя simple_format или .html_safe или sanitize (имя поля). Должен ли я санировать себя во всех своих взглядах на каждое поле, а также на вставку? Сделать это вручную повсюду не кажется очень рельсным.

Спасибо за любую помощь

4b9b3361

Ответ 1

TL; DR
Что касается ввода и запросов пользователя: Обязательно всегда используйте методы запросов активной записи (например, .where) и избегайте пропускать параметры с использованием интерполяции строк; передавать их как значения хэш-параметров или в качестве параметризованных операторов.

Относительно рендеринга потенциально небезопасного содержимого html/javascript, создаваемого пользователем. Как и в случае с Rails 3, текст html/javascript автоматически экранируется автоматически, поэтому он отображается как обычный текст на странице, а не интерпретируется как html/javascript, поэтому вам не нужно явно дезинфицировать (или использовать <%= h(potentially_unsafe_user_generated_content)% >

Если я правильно вас понимаю, вам не нужно беспокоиться о дезинфекции данных таким образом, если вы правильно используете методы запросов активной записи. Например:

Давайте скажем, что наша карта параметров выглядит так, в результате того, что злоумышленник вводит следующую строку в поле user_name:

:user_name => "(select user_name from users limit 1)"

Плохой путь (не делайте этого):

Users.where("user_name = #{params[:id}") # string interpolation is bad here

Результирующий запрос будет выглядеть так:

SELECT `users`.* FROM `users` WHERE (user_name = (select user_name from users limit 1))

Прямая интерполяция строк таким образом помещает литеральное содержимое значения параметра с ключом :user_name в запрос без дезинфекции. Как вы, вероятно, знаете, вредоносный ввод пользователя рассматривается как простой SQL-код, и опасность довольно ясна.

Хороший способ (сделайте это):

Users.where(id: params[:id]) # hash parameters

ИЛИ

Users.where("id = ?", params[:id]) # parameterized statement

Результирующий запрос будет выглядеть так:

SELECT `users`.* FROM `users` WHERE user_name = '(select user_name from users limit 1)'

Итак, как вы можете видеть, Rails на самом деле дезориентирует его для вас, пока вы передаете параметр в виде хэша или параметра метода (в зависимости от того, какой метод запроса вы используете).

Случай для дезинфекции данных о создании новых записей модели на самом деле не применяется, поскольку методы new или create ожидают хеш значений. Даже если вы попытаетесь ввести небезопасный код SQL в хеш, значения хеша обрабатываются как простые строки, например:

User.create(:user_name=>"bobby tables); drop table users;")

Результаты запроса:

INSERT INTO `users` (`user_name`) VALUES ('bobby tables); drop table users;')

Итак, такая же ситуация, как и выше.

Надеюсь, это поможет. Дайте мне знать, если я пропустил или что-то не понял.

Edit Что касается экранирования html и javascript, то короткая версия - это то, что ERB "ускользает" от вашего строкового содержимого, так что он рассматривается как обычный текст. Вы можете обработать его как html, если вы действительно этого хотите, выполнив your_string_content.html_safe.

Однако просто делать что-то вроде <%= your_string_content %> совершенно безопасно. Содержимое рассматривается как строка на странице. Фактически, если вы изучите DOM с помощью инструментов разработчика Chrome или Firebug, вы должны фактически просмотреть кавычки вокруг этой строки.

Ответ 2

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

Как ActiveRecord, так и ActionController предоставляют методы для дезактивации ввода sql.

В частности, из ActiveRecord::Sanitization::ClassMethods у вас есть sanitize_sql_for_conditions и два других псевдонима:   sanitize_conditions и sanitize_sql. Эти три делают буквально то же самое.

sanitize_sql_for_conditions

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

Однако в ActiveRecord у вас также есть

sanitize_sql_for_assignment, который

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

  • Обратите внимание, что эти методы включены в ActiveRecord:: Base и , поэтому включены по умолчанию в любую модель ActiveRecord.

С другой стороны, в ActionController у вас есть ActionController::Parameters, который позволяет вам

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

params = ActionController::Parameters.new(user: { name: 'Bryan', age: 21 })
req  = params.require(:user) # will throw exception if user not present
opt  = params.permit(:name)  # name parameter is optional, returns nil if not present
user = params.require(:user).permit(:name, :age) # user hash is required while `name` and `age` keys are optional

Параметры magic называются Strong Parameters, docs here.

Я надеюсь, что это поможет кому угодно, только чтобы узнать и демистифицировать Rails!:)