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

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

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

2.06.2009 20:01:38
Также смотрите: «Почему Google Prepend while (1) к их ответу JSON?» stackoverflow.com/questions/2669690/…
Chloe 20.02.2013 03:56:24
10 ОТВЕТОВ
РЕШЕНИЕ

Что просходит

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

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

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

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

Документация API описывает подробности о метатеге:

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

1456
12.05.2018 08:40:52
@Faisal, возможно ли тогда, что злоумышленник просто прочитает / перехватит «скрытый» элемент формы для Сервиса A и получит этот уникальный токен, сгенерированный для пользователя - учитывая, что он получил доступ к сеансу, запущенному пользователем для службы А?
marcamillion 25.10.2010 22:18:02
@marcamillion: если кто-то похитил вашу сессию в службе А, то маркер подлинности не защитит вас. Угонщик сможет подать запрос, и ему будет разрешено продолжить.
Faisal 26.10.2010 07:02:43
@zabba: Rails вызывает исключение ActionController :: InvalidAuthenticityToken, если форма отправляется без правильного токена. Вы можете спасти_из исключения и выполнить любую обработку, какую захотите.
Faisal 31.01.2011 07:41:53
re «Также следите за тем, чтобы не делать никаких запросов GET, которые потенциально могут изменить ресурсы на сервере». - это включает в себя не использование match () в маршрутах, которые потенциально могут разрешать запросы GET к действиям контроллера, предназначенным для получения только POST
Steven Soroka 25.04.2012 18:25:14
«... и запрос должен быть идемпотентным (если вы выполняете одну и ту же команду несколько раз, вы должны каждый раз получать один и тот же результат)». Просто тонкое уточнение здесь. Безопасный означает отсутствие побочных эффектов. Идемпотент означает один и тот же побочный эффект, независимо от того, сколько раз вызывается услуга. Все безопасные услуги по своей природе идемпотентны, потому что нет побочных эффектов. Многократный вызов GET для ресурса текущего времени будет каждый раз возвращать другой результат, но это безопасно (и, следовательно, идемпотентно).
erturne 18.08.2012 16:25:46

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

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

<%= form_authenticity_token %>

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

Вы можете прочитать больше об этом в документации .

137
31.01.2011 00:54:30

Это Authenticity Tokenметод 'rails' для предотвращения 'атак подделки межсайтовых запросов (CSRF или XSRF)' .

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

39
2.06.2009 20:17:18

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

27
30.08.2011 23:52:45

Что такое CSRF?

Токен подлинности является контрмерой для подделки межсайтовых запросов (CSRF). Вы спрашиваете, что такое CSRF?

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

Сценарий :

  • Посетите сайт вашего банка, войдите.
  • Затем посетите сайт злоумышленника (например, рекламную рекламу ненадежной организации).
  • На странице злоумышленника есть форма с теми же полями, что и у банковской формы «Перевод средств».
  • Атакующий знает данные вашей учетной записи и имеет предварительно заполненные поля формы для перевода денег с вашей учетной записи на учетную запись злоумышленника.
  • На странице злоумышленника есть Javascript, который отправляет форму в ваш банк.
  • Когда форма отправлена, браузер включает ваши куки для сайта банка, включая токен сеанса.
  • Банк переводит деньги на счет злоумышленника.
  • Форма может быть в невидимом фрейме, поэтому вы никогда не узнаете, что атака произошла.
  • Это называется подделкой межсайтовых запросов (CSRF).

CSRF решение :

  • Сервер может пометить формы, которые пришли с самого сервера
  • Каждая форма должна содержать дополнительный токен аутентификации в качестве скрытого поля.
  • Токен должен быть непредсказуемым (злоумышленник не может его угадать).
  • Сервер предоставляет действительный токен в формах на своих страницах.
  • Сервер проверяет токен при отправке формы, отклоняет формы без правильного токена.
  • Пример токена: идентификатор сеанса, зашифрованный секретным ключом сервера.
  • Rails автоматически генерирует такие токены: смотрите поле ввода authenticity_token в каждой форме.
88
20.11.2015 16:12:00
Вот версия этого же объяснения, которая является менее точной, но также и менее абстрактной: stackoverflow.com/a/33829607/2810305
Lutz Prechelt 20.11.2015 14:59:06
Я не уверен, но позволяют ли современные браузеры отправлять не идемпотентные запросы (POST / PUT / DELETE) в другой домен? Я думаю, в самом браузере должна быть защита от подобных вещей
divideByZero 22.09.2016 20:31:35

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

 <%= token_tag nil %>

создавать

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

где угодно

34
1.08.2012 05:12:06
Это было полезно для меня. На самом деле я пытался сделать это XSSна странице входа в систему, но не для гнусных целей, а для создания нового сеанса с предварительно заполненным именем пользователя. Теперь я знаю, что могу просто использовать value="token_value".
Michael - Where's Clay Shirky 24.02.2014 16:03:51

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

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

Почему это требуется

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

11
26.01.2016 08:31:06
На самом деле, разве не наоборот? GET является идемпотентным, поскольку его вызов не должен изменять состояние системы, где глаголы PUT POST и DELETE НЕ являются идемпотентными глаголами, поскольку они изменяют состояние системы. IE: authenticity_token требуется в случае НЕ идемпотентных методов.
Jean-Théo 10.07.2014 09:26:50
@ Жан-Добе, ума: идемпотент означает, что если сделать дважды, действие происходит только один раз. GET, PUT и DELETE являются идемпотентными: w3.org/Protocols/rfc2616/rfc2616-sec9.html Ключевым свойством здесь является не идемпотентность, но если метод изменяет или нет данные, которые называются «Безопасный метод» или нет.
Ciro Santilli 冠状病毒审查六四事件法轮功 12.11.2014 20:14:11

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

На моем сайте 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параметр, и я никак не мог бы угадать его, поскольку это огромное случайное число.

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

Политика единого происхождения

Но что, если злоумышленник сделал два запроса с JavaScript, один для чтения токена, а второй для передачи?

Одного шаблона токена синхронизатора недостаточно, чтобы предотвратить это!

Здесь на помощь приходит политика одного происхождения, как я объяснил по адресу: https://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important/72569# 72569

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

Рассмотрено по адресу: Rails: как работает csrf_meta_tag?

В принципе:

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

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

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

Другие профилактические подходы

44
2.08.2019 07:54:47
Спасибо, но ваша точка зрения о том, что вы полагаетесь на одну и ту же политику происхождения, чтобы не иметь возможности просто читать токен CSRF, кажется ошибочной. Итак, сначала вы говорите, что можете POST к другому источнику, но не можете прочитать из него, кажется странным, но я думаю, это правильно, но вы могли бы вставить тег изображения или сценария с помощью get на страницу и связать обработчик для анализа ответа и получить это да?
bjm88 28.02.2017 00:29:32
@ bjm88 внедрить скрипт где? На вашем сайте или на атакованном сайте? Если сайт атакован, разрешение внедрения скрипта является широко известным недостатком безопасности и эффективно закладывает сайт. Каждый веб-сайт должен бороться с этим путем ввода санитарии. Для изображений я не вижу, как их можно использовать для атаки. На атакующем сайте: вы можете изменить свой браузер, чтобы разрешить чтение, и, таким образом, автоматически закладывать себя по своему желанию :-), но приличные браузеры предотвращают его по умолчанию, попробуйте.
Ciro Santilli 冠状病毒审查六四事件法轮功 28.02.2017 05:42:48

Что такое аутентификационный токен?

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

Зачем нужен аутентификационный токен?

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

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

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

6
4.02.2017 15:54:11

Маркер подлинности используется для предотвращения атак подделки межсайтовых запросов (CSRF). Чтобы понять маркер подлинности, вы должны сначала понять атаки CSRF.

CSRF

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ну, просто не посещайте опасные сайты, и все будет в порядке.

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

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

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

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

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

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

Атака межсайтового скриптинга (XSS) - вот как. Но это другая уязвимость для другого дня.

43
23.07.2018 21:37:48