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

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

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

856
задан Ricardo Acras 02 июня '09 в 23:01
источник поделиться

10 ответов

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

Когда пользователь просматривает форму для создания, обновления или уничтожения ресурса, приложение 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 являются идемпотентными. Он объясняет это лучше, чем я сделал здесь.

1349
ответ дан Faisal 15 окт. '09 в 14:52
источник поделиться

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

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

<%= form_authenticity_token %>

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

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

126
ответ дан Topher Fangio 02 июня '09 в 23:16
источник поделиться

Что такое CSRF?

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

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

Сценарий

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

Решение CSRF:

  • Сервер может отмечать формы, которые поступают с самого сервера
  • Каждая форма должна содержать дополнительный токен аутентификации как скрытое поле.
  • Токен должен быть непредсказуемым (злоумышленник не может догадаться).
  • Сервер предоставляет действительный токен в формах на своих страницах.
  • Сервер проверяет токен при отправке формы, отклоняет формы без соответствующего токена.
  • Пример токена: идентификатор сеанса, зашифрованный секретным ключом сервера.
  • Rails автоматически генерирует такие маркеры: см. поле ввода authenticity_token в каждой форме.
73
ответ дан Rose Perrone 13 июня '12 в 4:54
источник поделиться

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

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

34
ответ дан andi 02 июня '09 в 23:17
источник поделиться

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

На моем веб-сайте 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 также пытается обновить токен в формах устаревших кешированных фрагментов.

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

33
ответ дан Ciro Santilli 包子露宪 六四事件 法轮功 12 нояб. '14 в 23:30
источник поделиться

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

 <%= token_tag nil %>

создать

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

в любом месте

31
ответ дан Yuan He 01 авг. '12 в 8:12
источник поделиться

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

24
ответ дан jdp 31 авг. '11 в 2:52
источник поделиться

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

CSRF

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

введите описание изображения здесь

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

введите описание изображения здесь

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

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

Как сервер знает об этом? Потому что нет 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!

введите описание изображения здесь

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

Этого недостаточно. Что делать, если кто-то размещает этот образ в 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 не видит токен аутентификации, отправленный вместе с запросом, он не будет считать запрос безопасным.

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

введите описание изображения здесь

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

17
ответ дан Adam Zerner 14 апр. '17 в 7:33
источник поделиться

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

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

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

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

8
ответ дан uma 26 февр. '14 в 14:13
источник поделиться

Что такое authentication_token?

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

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

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

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

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

3
ответ дан Pradeep Sapkota 22 июля '16 в 5:02
источник поделиться

Другие вопросы по меткам