CSRF в Laravel
Хакеры, используя данные залогиненных пользователей в куках различных сайтов (начиная от банальных блогов, заканчивая сайтами банков), производят от их лица различные действия. Спрашивается, как хакеры узнают данные пользователей, чтобы отправить запрос от их имени?
Самое интересное что ничего они не узнают, пользователи сами дают согласие на произведение действий, угодных хакерам.
Всем неоднократно приходили на почту письма с содержанием вида «Смотри, какие милые котики» или «Не думал, что ты такое способен. Смотри, что я нашёл» и какими-то левыми ссылками с зашифрованными url и текстом, побуждающим по ним перейти.
При CSRF атаке после перехода по такой ссылке отправляется запрос на атакуемый ресурс — банка, блога или другой сайт с необходимыми параметрами, содержащие текст комментария, размер денежного перевода хакеру и т.д. И если вы будете залогинены на сайте, а атакуемый сайт будет хранить данные залогиненных пользователей в куках клиентских браузеров, то такой запрос будет с лёгкостью обработан. В результате у вас со счёта уйдут деньги в неизвестном направлении или появится комментарий с абсолютно произвольным содержанием на блоге.
Как уберечься от CSRF
Мы должны учитывать возможность данных атак на пользователей создаваемых сайтов и всячески их предотвращать.
- Не хранить данные авторизаций в куках браузера, для этого есть сессии на стороне сервера
- Важные действия производить с помощью
POST
,PUT
,DELETE
,PATCH
HTTP запросов, но никак неGET
,HEAD
,OPTIONS
иTRACE
, эти запросы подходят для получения данных сайта, а не для изменения состояния сервера - При разработке пользоваться наработками опытных программистов, а лучше целых команд, где обязательно должны быть специалисты по кибербезопасности
Защита от CSRF в Laravel
Метод защиты Laravel, заключается в указании CSRF токена при отправке запроса, который сверяется на сервере перед его обработкой.
CSRF token в Laravel представляет собой строку из 40 случайных символов, которая генерируется при создании новой сессии приложения, при активности нового пользователя на сайте.
Таким образом, проверка CSRF токена перед обработкой запроса позволяет выяснить, что данный запрос был отправлен конкретным пользователем, а не кем-то вместо него.
Если отправите запрос, через HTML форму методом POST
, PUT
, DELETE
или PATCH
, то получите ошибку проверки CSRF токена.
Чтобы запрос отправился, необходимо в форму, с помощью которой отправляется запрос, добавить скрытое поле со значением CSRF token с помощью специальной функции-хэлпера csfr_field
следующим образом:
<form method="post">
{{ csrf_field() }}
</form>
Разработчики Laravel рекомендуют для дополнительной защиты AJAX запросов добавлять CSRF токен ко всем запросам на уровне JavaScript путём указания токена в значении метатэга, размещённого в секции head HTML-документа:
<meta name="csrf-token" content="{{ csrf_token() }}">
Считывание данного значения в JS производится следующей JQuery-конструкцией:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
При отправке же GET запроса для успешной его обработки сервером CSRF token указывать не нужно. Но, как известно, данный тип запроса и так считается небезопасным благодаря указанию параметров в URL запроса, которые можно увидеть в браузере.
Кстати, текущий CSRF токен указывается в качестве значения переменной COOKIE X-XSRF-TOKEN
, которая присутствует в каждом ответе сервера. Поэтому иногда его будет удобнее использовать, особенно в ситуациях, когда значение CSRF токена необходимо получить в JavaScript, где хэлперы Laravel, как известно, не работают.
Обход CSRF защиты
Иногда возникают ситуации, когда запрос нужно не проверять на наличие в его параметрах CSRF токена. Особенно это актуально при работе с различными сервисами по API, ресурсы не будут знать какой CSRF токен отправить при посылке ответа Laravel сайту.
За чтение CSRF token и его проверку перед выполнением запроса ответственны VerifyCsrfToken.php
, который и генерирует исключение exception
при попытке отправить POST запрос без указания токена.
Мы можем им воспользоваться в случаях, когда нам необходимо будет обойти CSRF защиту, указав необходимые url в потомке оригинального ласса App\Http\Middleware\VerifyCsrfToken
следующим образом:
App/Http/Middleware/VerifyCsrfToken.php<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
//url запросов, для которых не нужно проверять CSRF токен
];
}