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

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

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

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, и исключить). Также убедитесь, что не разрешены запросы GET, которые потенциально могут изменять ресурсы на сервере.


EDIT: Регистрация комментарий @erturne относительно запросов GET, являющихся идемпотентными. Он объясняет это лучше, чем я.


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

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

<%= form_authenticity_token %>

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

вы можете подробнее об этом читайте в разделе документация.


Что такое CSRF?

маркер подлинности является контрмерой для подделки межсайтового запроса (CSRF). Что такое CSRF, спросите вы?

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

сценарий:

  • посетите сайт вашего банка, войдите в систему.
  • затем посетите сайт злоумышленника (например, спонсируемое объявление от ненадежной организации).
  • атакующего страницы включает форму с теми же полями, что и форма банка "Перевод средств".
  • злоумышленник знает информацию о вашем счете и имеет предварительно заполненные поля формы для перевода денег с вашего счета на счет злоумышленника.
  • страница злоумышленника включает Javascript, который отправляет форму в ваш банк.
  • когда форма отправляется, браузер включает ваши файлы cookie для сайта банка, включая токен сеанса.
  • банковские переводы денег злоумышленнику счет.
  • форма может быть в iframe, который невидим, поэтому вы никогда не знаете, что атака произошла.
  • это называется подделкой межсайтового запроса (CSRF).

решение CSRF:

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

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

мой сайт 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>

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

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

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

шаблон токена синхронизатора работает из-за Та Же Политика Происхождения: если бы я мог сделать запрос XHR 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 также пытается обновить токен в формах в устаревших кэшированных фрагментах.

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


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

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


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

 <%= token_tag nil %>

создать

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

в любом месте


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

CSRF в

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

enter image description here

хакер может просто отправить HTTP-запрос на сервер говорю GET /transfer?amount=00000&account-to=999999, да?

enter image description here

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

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

откуда сервер это знает? Потому что нет session_id файл cookie проверки подлинности запроса.

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

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

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

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

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

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

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

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

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

enter image description here

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

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

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

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

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

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

enter image description here

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


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


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

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

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

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


Что такое authentication_token ?

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

почему authentication_token надо ?

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

Как добавить authentication_token в форму ?

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