Маркер подлинности используется для предотвращения атак подделки межсайтовых запросов (CSRF). Чтобы понять маркер подлинности, вы должны сначала понять атаки CSRF.
CSRF
Предположим, что вы являетесь автором bank.com
. На вашем сайте есть форма, которая используется для перевода денег на другой счет с GET-запросом:
![enter image description here](https://i.stack.imgur.com/QV7s3.png)
Хакер может просто отправить HTTP-запрос на сервер со словами GET /transfer?amount=$1000000&account-to=999999
, верно?
![enter image description here](https://i.stack.imgur.com/acVPX.png)
Неправильно. Атака хакеров не сработает. Сервер будет в основном думать?
А? Кто этот парень пытается инициировать перевод. Это не владелец аккаунта, это точно.
Откуда сервер знает это? Поскольку session_id
cookie не аутентифицирует запрашивающую сторону.
Когда вы входите под своим именем пользователя и паролем, сервер устанавливает в вашем браузере файл cookie session_id
. Таким образом, вам не нужно аутентифицировать каждый запрос с вашим именем пользователя и паролем. Когда ваш браузер отправляет файл cookie session_id
, сервер знает:
О, это Джон Доу. Он успешно вошел в систему 2,5 минуты назад. Ему хорошо идти.
Хакер может подумать:
Хм. Обычный HTTP-запрос не сработает, но если бы я мог взять руку на это session_id
печенье, я был бы золотым.
В браузере пользователей есть набор файлов cookie для домена bank.com
. Каждый раз, когда пользователь отправляет запрос на домен bank.com
, все куки отправляются вместе. Включая session_id
cookie.
Так что, если хакер может вы сделать запрос 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!
![enter image description here](https://i.stack.imgur.com/UGrgL.png)
Ну, просто не посещайте опасные сайты, и все будет в порядке.
Этого недостаточно. Что если кто-то разместит это изображение на 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 не видит токен аутентификации, отправленный вместе с запросом, он не будет считать запрос безопасным.
Как злоумышленник должен знать, что это за токен? Разное значение генерируется случайным образом при каждом создании формы:
![enter image description here](https://i.stack.imgur.com/4AJHB.gif)
Атака межсайтового скриптинга (XSS) - вот как. Но это другая уязвимость для другого дня.