Я много читал об этом и до сих пор не понимаю этого. Допустим, у меня есть домен с формой, доступной только авторизованным пользователям, чтобы оставлять комментарии к какому-либо контенту:
my_form.php
<form action="post_comment.php" method="post">
<textarea name="comment"></textarea>
<input type="hidden" name="csrf_token" value="<?php print $csrf_token; ?>" />
<input type="submit" value="Post" />
</form>
post_comment.php
<?php
if(!isset($_POST['csrf_token']) || !CSRFToken::validate($_POST['csrf_token'])){
print "Invalid CSRF-Token!";
exit;
}
[...]
?>
Post_comment.php отклонит любой запрос, если значение токена «csrf_token» не отправлено или недействительно. Поэтому мы запрещаем злоумышленникам использовать наш post_comment.php.
НО, как запретить атакующему GET /my_form.php, прочитать значение csrf_token из формы и POST в post_comment.php, используя его? Что мне не хватает?
Маркер CSRF является случайным и уникальным для каждой сессии. Следовательно, злоумышленник может получить значение этого токена, которое связано с его / ее собственными учетными данными, но не с потенциальной жертвой.
CSRF — это атака, когда жертва регистрируется на вашем сайте (имеет сессионный cookie), когда у вас нет сеанса, тогда CSRF не требуется.
Жертва посещает злой другой сайт с тем же браузером.
Теперь этот сайт может отправлять запрос на ваш сайт (с помощью куки-файла и, следовательно, логина жертвы), что можно предотвратить с помощью токена CSRF, поскольку злой сайт может отправлять запросы с помощью куки-файлов, но не может читать ответы на запросы. (Та же политика происхождения).
Вы можете отключить это поведение в своем (персональном) браузере, но оно включено по умолчанию, поскольку некоторые приложения зависят от него.