Понимание токена подлинности Rails

856

Я сталкиваюсь с некоторыми проблемами, касающимися токена аутентификации в Rails, поскольку я уже много раз.

Но я действительно не хочу просто решать эту проблему и продолжать. Мне бы очень хотелось понять токен аутентичности. Ну, на мой вопрос: у вас есть какой-то полный источник информации по этому вопросу или вы потратите свое время, чтобы объяснить здесь подробнее?

Теги:
authenticity-token

10 ответов

1349
Лучший ответ

Что произойдет

Когда пользователь просматривает форму для создания, обновления или уничтожения ресурса, приложение Rails создает случайный authenticity_token, сохраняет этот токен в сеансе и помещает его в скрытое поле в форме. Когда пользователь отправляет форму, Rails ищет authenticity_token, сравнивает его с тем, который хранится в сеансе, и если они соответствуют запросу, разрешено продолжить.

Почему это происходит

Поскольку токен аутентичности хранится в сеансе, клиент не может знать его значение. Это не позволяет людям отправлять формы в приложение Rails без просмотра формы внутри этого приложения. Представьте, что вы используете сервис A, вы вошли в службу, и все в порядке. Теперь представьте, что вы пошли использовать службу B, и вы видели понравившуюся вам картинку, и нажали на картинку, чтобы просмотреть ее более крупный размер. Теперь, если какой-либо злой код был там в службе B, он мог бы отправить запрос на обслуживание A (который вы вошли в систему) и попросить удалить свою учетную запись, отправив запрос на http://serviceA.com/close_account. Это то, что называется CSRF (Подпрограмма запроса на межсайтовый поиск).

Если служба A использует токены аутентификации, этот вектор атаки больше не применим, так как запрос из службы B не содержит правильный токен аутентификации и не будет разрешен для продолжения.

API docs описывает детали метатега:

Защита CSRF включается с помощью метода protect_from_forgery, который проверяет токен и сбрасывает сеанс, если он не соответствует тому, что ожидалось. Вызов этого метода создается для новых Rails приложений по умолчанию. Параметр токена по умолчанию называется authenticity_token. Имя и значение этого токена должно быть добавлено к каждому макету, который отображает формы, включая csrf_meta_tags в голове HTML.

Примечания

Имейте в виду, что Rails проверяет только не идемпотентные методы (POST, PUT/PATCH и DELETE). Запрос GET не проверяется на токен аутентификации. Зачем? потому что спецификация HTTP указывает, что запросы GET являются идемпотентными и должны не создавать, изменять или уничтожать ресурсы на сервере, а запрос должен быть идемпотентным (если вы выполняете ту же команду несколько раз, вы должны получить тот же результат каждый раз).

Также реальная реализация немного сложнее, как определено в начале, обеспечивая лучшую безопасность. Rails не выдает один и тот же сохраненный токен с каждой формой. Он также не генерирует и не сохраняет различный токен каждый раз. Он генерирует и хранит криптографический хеш в сеансе и выдает новые криптографические маркеры, которые могут быть сопоставлены с сохраненным, каждый раз, когда страница отображается. См. request_forgery_protection.rb.

Уроки

Используйте authenticity_token для защиты ваших методов без идемпотента (POST, PUT/PATCH и DELETE). Также не забудьте разрешить любые запросы GET, которые могли бы потенциально изменить ресурсы на сервере.


РЕДАКТИРОВАТЬ: Отметьте комментарий @erturne о том, что запросы GET являются идемпотентными. Он объясняет это лучше, чем я сделал здесь.

  • 24
    @Faisal, возможно ли тогда, что злоумышленник просто прочитает / перехватит «скрытый» элемент формы для службы A и получит этот уникальный токен, сгенерированный для пользователя - учитывая, что он получил доступ к сеансу, запущенному пользователем для службы А?
  • 1
    Например, путем захвата данных, возвращаемых из функции отладки? Просто мысль.
Показать ещё 28 комментариев
120

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

Если вы просто испытываете трудности с рельсами, лишающими доступ к AJAX script, вы можете использовать

<%= form_authenticity_token %>

чтобы создать правильный токен при создании вашей формы.

Подробнее об этом можно узнать в документации.

76

Что такое CSRF?

Подлинник аутентификации является контрмерой для подпрограммы подбора сайтов (CSRF). Что такое CSRF, спросите вы?

Это способ, которым злоумышленник может потенциально захватывать сеансы, даже не зная токенов сеанса.

Сценарий

  • Посетите сайт своего банка, выполните вход.
  • Затем посетите сайт злоумышленника (например, рекламное объявление из ненадежной организации).
  • Страница "Атакующий" включает форму с теми же полями, что и в форме банка "Transfer Funds".
  • Атакующий знает вашу учетную запись и имеет предварительно заполненные поля формы, чтобы переводить деньги со своей учетной записи на счет злоумышленника.
  • Страница Attacker включает Javascript, который отправляет форму в ваш банк.
  • Когда форма отправляется, браузер включает ваши файлы cookie для сайта банка, включая токен сеанса.
  • Банк переводит деньги на счет злоумышленника.
  • Форма может быть в iframe, которая невидима, поэтому вы никогда не знаете, что произошла атака.
  • Это называется Cross-Site Request Forgery (CSRF).

Решение CSRF:

  • Сервер может отмечать формы, которые поступают с самого сервера
  • Каждая форма должна содержать дополнительный токен аутентификации как скрытое поле.
  • Токен должен быть непредсказуемым (злоумышленник не может догадаться).
  • Сервер предоставляет действительный токен в формах на своих страницах.
  • Сервер проверяет токен при отправке формы, отклоняет формы без соответствующего токена.
  • Пример токена: идентификатор сеанса, зашифрованный секретным ключом сервера.
  • Rails автоматически генерирует такие маркеры: см. поле ввода authenticity_token в каждой форме.
  • 1
    Вот версия этого же объяснения, которая является менее точной, но также и менее абстрактной: stackoverflow.com/a/33829607/2810305
  • 0
    Я не уверен, но позволяют ли современные браузеры отправлять не идемпотентные запросы (POST / PUT / DELETE) в другой домен? Я думаю, в самом браузере должна быть защита от подобных вещей
34

Пример минимальной атаки, который будет предотвращен

На моем веб-сайте evil.com Я убеждаю вас представить следующую форму:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

Если вы вошли в свой банк с помощью файлов cookie сеанса, файлы cookie будут отправлены, и передача будет выполнена без вашего ведома.

Это означает, что токен CSRF вступает в игру:

  • с ответом GET, который возвратил форму, Rails отправляет очень длинный случайный скрытый параметр
  • когда браузер выполнит запрос POST, он отправит этот параметр вместе, и сервер примет его, только если он соответствует

Таким образом, форма в аутентичном браузере будет выглядеть так:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

Таким образом, моя атака потерпит неудачу, поскольку она не отправляет параметр authenticity_token, и я никак не мог догадаться, так как это огромное случайное число.

Этот метод профилактики называется Шаблон маркера синхронизатора.

Рисунок токена синхронизатора работает из-за Одинаковая политика происхождения: если бы я мог сделать запрос XET GET ваш банк от evil.com, и прочитайте результат, я бы мог просто прочитать токен, а затем сделать запрос позже. Я объяснил это далее: https://security.stackexchange.com/a/72569/53321

Я настоятельно рекомендую вам прочитать руководство OWASP по этому и любому другому вопросу безопасности.

Как Rails отправляет маркеры

Покрытие: Rails: Как работает csrf_meta_tag?

В принципе:

  • HTML-помощники, такие как form_tag добавьте скрытое поле в форму для вас, если это не форма GET

  • AJAX обрабатывается автоматически с помощью jquery-ujs, который читает токен из элементов meta, добавленных в ваш заголовок, csrf_meta_tags (присутствует в шаблоне по умолчанию) и добавляет его к любому сделанному запросу.

    uJS также пытается обновить токен в формах устаревших кешированных фрагментов.

Другие меры профилактики

  • 0
    Спасибо, но ваша точка зрения о том, что вы полагаетесь на одну и ту же политику происхождения, чтобы не иметь возможности сначала просто прочитать токен CSRF, кажется ошибочной. Итак, сначала вы говорите, что можете POST к другому источнику, но не можете прочитать из него, кажется странным, но я думаю, это правильно, но вы могли бы вставить тег изображения или сценария с помощью get на страницу и связать обработчик для анализа ответа и получить это да?
  • 0
    @ bjm88 внедрить скрипт где? На вашем сайте или на атакованном сайте? Если сайт атакован, разрешение внедрения скриптов является широко известным недостатком безопасности и эффективно закладывает сайт. Каждый веб-сайт должен бороться с этим путем ввода санитарии. Для изображений я не вижу, как их можно использовать для атаки. На атакующем сайте: вы можете изменить свой браузер, чтобы разрешить чтение, и, таким образом, автоматически закладывать себя по своему желанию :-), но приличные браузеры по умолчанию запрещают это, попробуйте.
33

Authenticity Token - метод рельсов prevent ' атаки на межсайтовый запрос (CSRF или XSRF).

Проще говоря, он гарантирует, что запросы PUT/POST/DELETE (методы, которые могут изменять содержимое) в вашем веб-приложении сделаны из клиентского браузера, а не стороннего (злоумышленника), который имеет доступ к cookie, созданный на стороне клиента.

30

так как Authenticity Token так важен, а в Rails 3.0+ вы можете использовать

 <%= token_tag nil %>

создать

<input name="authenticity_token" type="hidden" value="token_value">

в любом месте

  • 0
    Это было полезно для меня. На самом деле я пытался сделать XSS на странице входа в систему, не для гнусных целей, а для создания нового сеанса с предварительно заполненным именем пользователя. Теперь я знаю, что могу просто использовать value="token_value" .
24

Остерегайтесь механизма аутентификации подлинности может привести к условиям гонки, если у вас есть несколько одновременных запросов от одного и того же клиента. В этой ситуации ваш сервер может генерировать несколько токенов аутентификации, когда их должно быть только одно, а клиент, получающий более ранний токен в форме, не сможет выполнить следующий запрос, потому что токен сеанса cookie был перезаписан. Здесь написана запись и это не совсем тривиальное решение: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/

17

Маркер аутентификации используется для предотвращения атак типа Cross-Site Request Forgery (CSRF). Чтобы понять токен аутентичности, вы должны сначала понять атаки CSRF.

CSRF

Предположим, что вы являетесь автором bank.com. На вашем сайте есть форма, используемая для перевода денег на другую учетную запись с запросом GET:

Изображение 4149

Хакер может просто отправить HTTP-запрос серверу, сказав GET /transfer?amount=$1000000&account-to=999999, правильно?

Изображение 4150

Неправильно. Атака хакеров не сработает. Сервер будет в основном думать?

А? Кто этот парень пытается начать передачу. Это не владелец учетной записи, это точно.

Как сервер знает об этом? Потому что нет session_id cookie, аутентифицирующий запросчика.

Когда вы входите в систему со своим именем пользователя и паролем, сервер устанавливает cookie session_id в вашем браузере. Таким образом, вам не нужно аутентифицировать каждый запрос с вашим именем пользователя и паролем. Когда ваш браузер отправляет cookie session_id, сервер знает:

О, это Джон Доу. Он подписал контракт успешно 2,5 минуты назад. Он хорошо пошел.

Хакер может подумать:

Хм. Обычный HTTP-запрос не будет работать, но если бы я мог получить свою руку от этого cookie session_id, я был бы золотым.

В браузере пользователей есть куча файлов cookie, установленных для домена bank.com. Каждый раз, когда пользователь делает запрос в домен bank.com, все файлы cookie отправляются вместе. Включая cookie session_id.

Итак, если хакер может заставить вас сделать запрос GET, который переводит деньги на его счет, он будет успешным. Как он мог обмануть вас в этом?  С подделкой запроса на межсайтовый запрос.

Это довольно просто, на самом деле. Хакер мог просто заставить вас посетить его сайт. На его веб-сайте у него может быть следующий тег изображения:

<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

Когда браузер пользователей встретит этот тег изображения, он будет делать запрос GET на этот URL-адрес. И поскольку запрос поступает из его браузера, он отправит вместе с ним все файлы cookie, связанные с bank.com. Если пользователь недавно подписался на bank.com... будет установлен файл cookie session_id, и сервер подумает, что пользователь должен перевести 1 000 000 долларов на счет 999999!

Изображение 4151

Хорошо, просто не посещайте опасные сайты, и все будет хорошо.

Этого недостаточно. Что делать, если кто-то размещает этот образ в Facebook и появляется на вашей стене? Что делать, если он вводится на сайт вашего посещения с помощью атаки XSS?

Это не так уж плохо. Только запросы GET уязвимы.

Не верно. Форма, которая отправляет запрос POST, может динамически генерироваться. Вот пример из Rails Guide on Security:

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

Идентификатор подлинности

Когда ваш ApplicationController имеет это:

protect_from_forgery with: :exception

Это:

<%= form_tag do %>
  Form contents
<% end %>

Скомпилировано в это:

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

В частности, генерируется следующее:

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

Чтобы защитить от атак CSRF, если Rails не видит токен аутентификации, отправленный вместе с запросом, он не будет считать запрос безопасным.

Как злоумышленник должен знать, что это за токен? Другое значение генерируется случайным образом каждый раз, когда формируется форма:

Изображение 4152

Атака Cross Site Scripting (XSS) - это как. Но это другая уязвимость для другого дня.

8

Методы Где authenticity_token требуется

authenticity_token требуется в случае идемпотентных методов, таких как post, put и delete, потому что методы Idempotent влияют на данные.

Зачем требуется

Требуется предотвратить злые действия. authenticity_token хранится в сеансе, всякий раз, когда на веб-страницах создается форма для создания или обновления ресурсов, то токен аутентификации хранится в скрытом поле и отправляется с формой на сервер. Перед выполнением действия пользователь отправил authenticity_token, перекрестно проверено с помощью authenticity_token, сохраненного в сеансе. Если authenticity_token совпадает, то процесс продолжается, иначе он не выполняет действия.

  • 3
    На самом деле, разве не наоборот? GET является идемпотентным, поскольку его вызов не должен изменять состояние системы, где глаголы PUT POST и DELETE НЕ являются идемпотентными глаголами, поскольку они изменяют состояние системы. IE: authenticity_token требуется в случае НЕ идемпотентных методов.
  • 2
    @ Жан-Добе, ума: идемпотент означает, что если сделать дважды, действие происходит только один раз. GET, PUT и DELETE являются идемпотентными: w3.org/Protocols/rfc2616/rfc2616-sec9.html Ключевым свойством здесь является не идемпотентность, но если метод изменяет или нет данные, которые называются «Безопасный метод» или нет.
3

Что такое authentication_token?

Это случайная строка, используемая приложением rails, чтобы убедиться, что пользователь запрашивает или выполняет действие со страницы приложения, а не из другого приложения или сайта.

Почему требуется аутентификация_token?

Чтобы защитить ваше приложение или сайт от подделки запроса на межсайтовый сайт.

Как добавить аутентификацию_token в форму?

Если вы создаете форму с использованием тега form_for, то автоматически добавляется идентификатор_имя_науки, вы можете использовать <%= csrf_meta_tag %>.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню