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

Как работает Rails CSRF?

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?

4b9b3361

Ответ 1

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

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

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

def handle_unverified_request
  raise(ActionController::InvalidAuthenticityToken)
end

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

Ответ 2

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 ошибок, вместо этого сеанс будет be reset. Пользователи могут переопределить это поведение путем переопределения handle_unverified_request в своих контроллеры.

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