Маркер подлинности используется для предотвращения атак подделки межсайтовых запросов (CSRF). Чтобы понять маркер подлинности, вы должны сначала понять CSRF-атаки.
CSRF
Предположим, что вы являетесь автором bank.com
. У вас есть форма на вашем сайте, которая используется для перевода денег на другой счет с запросом GET:
Хакер может просто отправить HTTP-запрос на сервер, говоря GET /transfer?amount=$1000000&account-to=999999
, верно?
Неправильно. Атака хакеров не сработает. Сервер будет в принципе думать?
А? Кто этот парень пытается инициировать перевод. Это не владелец аккаунта, это точно.
Как сервер знает это? Потому что нет session_id
cookie, аутентифицирующего запрашивающего.
Когда вы входите под своим именем пользователя и паролем, сервер устанавливает session_id
cookie в вашем браузере. Таким образом, вам не нужно аутентифицировать каждый запрос с вашим именем пользователя и паролем. Когда ваш браузер отправляет session_id
куки, сервер знает:
О, это Джон Доу. Он успешно вошел в систему 2,5 минуты назад. Ему хорошо идти.
Хакер может подумать:
Хм. Обычный HTTP-запрос не сработает, но если бы я мог взять руку на этот session_id
cookie, я был бы золотым.
В браузере пользователей для 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="✓" />
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Form contents
</form>
В частности, генерируется следующее:
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Для защиты от CSRF-атак, если Rails не увидит токен аутентификации, отправленный вместе с запросом, он не будет считать запрос безопасным.
Как злоумышленник должен знать, что это за токен? Разное значение генерируется случайным образом каждый раз, когда генерируется форма:
Атака межсайтового скриптинга (XSS) - вот как. Но это другая уязвимость для другого дня.