Rails 3 CSRF токен все еще отправляет - PullRequest
3 голосов
/ 25 марта 2020

Я работаю в устаревшем рельсовом приложении и пытаюсь устранить некоторые уязвимости CSRF. Если я удалю скрытое поле CSRF из формы, я все равно смогу успешно отправить форму.

Единственным признаком того, что что-то не так, является предупреждение в журналах: WARNING: Can't verify CSRF token authenticity.

Есть некоторые страницы, где protect_from_forgery будет перехватывать запрос, и приложение будет обрабатывать sh, если токена csrf нет, но его попадание и промах зависят от страницы: например. страница входа в систему работает без токена, но страница обновления пользователя не работает.

Я пытался придумать собственную стратегию (предложенную Mar c Gauthier ) для protect_from_forgery что-то вроде:

protect_from_forgery with: :MyStrategy

class MyStrategy
  byebug
  def initialize(controller)
    @contriller = controller
  end

  def handle_unverified_request
    puts "HELLO!"
    Rails.logger.warn [
      "handle_unverified_request",
      "#{@controller.controller_name}-#{@controller.action_name}"
    ].join(" - ")

  end
end

Похоже, это ничего не дало при запуске приложения, вызов byebug приостановится, но я никогда не получаю сообщение puts или журнал ошибок.

Я также попробовал обычные стратегии, такие как with: :exception, но ничего не меняется, некоторые страницы работают, а некоторые нет, но они согласуются.

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Обычно важно защитить сеанс вошедших в систему пользователей от CSRF, поэтому во многих приложениях обычно отключают защиту при входе / выходе из системы, чтобы законные пользователи не могли получить ошибки. В большинстве случаев RF не может причинить особого вреда, если сеанс все равно будет завершен / сброшен.

Ищите skip_before_action :verify_authenticity_token, отключая действие, которое устанавливается с помощью protect_from_forgery

Проверьте свой метод тестирования - скрытое поле формы не всегда необходимо, потому что рельсы также используют X-CSRF-Token заголовки для ajax форм. Чтобы правильно проверить защиту от подделки - выполните фактическую попытку подделки, например, с помощью curl.

Убедитесь, что config.action_controller.allow_forgery_protection не отключен для разработки / производства, а контроллер или его предки не имеют allow_forgery_protection перегружен и возвращает false для рассматриваемого запроса. Очень маловероятно, но приложение может иметь некоторые другие части защиты от подделки, см. request_forgery_protection.rb

PS. byebug в контексте класса не очень полезен для этого случая, более видимый способ - raise "Hello CSRF" в handle_unverified_request

0 голосов
/ 15 апреля 2020

Кажется, что Rails делал то, что должен был, просто сбрасывал сессию, что не имело бы значения для формы входа в систему или формы забытого пароля. Поскольку у нас было только protect_from_forgery (with: :exception не стало значением по умолчанию до тех пор, пока когда-нибудь в Rails 5 ).

Можно подумать, что добавление with: :exception будет работать, но это не так. Обходной путь - извлечь содержимое класса Exception и поместить его в application_controller:

 def handle_unverified_request
     raise ActionController::InvalidAuthenticityToken
  end

Это работает для форм входа в систему и забытых паролей, других форм (которые правильно не разрешали ошибочные запросы). через) остаются прежними, что довольно странно, потому что я предполагаю, что оба не справятся с InvalidAuthenticityToken raised.

Это, конечно, оставляет вопрос, почему protect_from_forgery with: :exception не работает?

...