Как работает защита Rails CSRF? - PullRequest
21 голосов
/ 15 февраля 2011

Rails поднимает InvalidAuthenticityToken, когда токен CSRF не совпадает. Но, прочитав источник , я не могу понять, как это происходит на самом деле. Я начинаю с получения дерева для этого класса:

$ ack --ignore-dir=test InvalidAuthenticityToken

actionpack/lib/action_controller/metal/request_forgery_protection.rb
4:  class InvalidAuthenticityToken < ActionControllerError #:nodoc:
17:  # which will check the token and raise an ActionController::InvalidAuthenticityToken

actionpack/lib/action_dispatch/middleware/show_exceptions.rb
22:      'ActionController::InvalidAuthenticityToken' => :unprocessable_entity

Только два попадания, игнорируя комментарий. Первое определение класса:

class InvalidAuthenticityToken < ActionControllerError #:nodoc:
end

Второй переводит исключение в код состояния HTTP. Защита от CSRF включается при вызове protect_from_forgery в контроллере, поэтому давайте посмотрим на это:

def protect_from_forgery(options = {})
  self.request_forgery_protection_token ||= :authenticity_token
  before_filter :verify_authenticity_token, options
end

Добавляет фильтр:

def verify_authenticity_token
  verified_request? || handle_unverified_request
end

Который вызывает это при сбое проверки:

def handle_unverified_request
  reset_session
end

Так как же на самом деле InvalidAuthenticityToken поднимается?

Ответы [ 2 ]

22 голосов
/ 15 февраля 2011

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

Кажется, что эта фиксация также продолжает закрывать CSRF-уязвимость , но я не вдавался в подробности этого.

Чтобы получить старое поведение, вы просто определили бы этот метод:

def handle_unverified_request
  raise(ActionController::InvalidAuthenticityToken)
end

Подробнее о CSRF и других проблемах безопасности Rails можно прочитать в Руководство по безопасности Ruby on Rails .

9 голосов
/ 15 февраля 2011

verify_authenticity_token раньше определялся как

verified_request? || raise(ActionController::InvalidAuthenticityToken)

но, как вы заметили, теперь он вызывает handle_unverified_request, что, в свою очередь, вызывает reset_session

Я не думаю, что Rails на самом деле выбрасывает это исключение.

http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails Состояния

После применения этого патча произошел сбой CSRF запросы больше не будут генерировать HTTP 500 ошибок, вместо сеанса быть сброшен Пользователи могут переопределить это поведение путем переопределения handle_unverified_request в своем собственном контроллеры.

https://github.com/rails/rails/commit/66ce3843d32e9f2ac3b1da20067af53019bbb034

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