Skip to content

3.3. Защита от CSRF

1. Введение

Межсайтовая подделка запросов (CSRF) — это тип вредоносной атаки, при которой выполняются несанкционированные команды от имени аутентифицированного пользователя. К счастью, Laravel упрощает защиту вашего приложения от атак CSRF.

1.1. Объяснение уязвимости

Если вы не знакомы с межсайтовой подделкой запросов, давайте рассмотрим пример того, как можно эксплуатировать эту уязвимость. Представьте, что в вашем приложении есть маршрут /user/email, который принимает запрос POST для изменения адреса электронной почты аутентифицированного пользователя. Скорее всего, этот маршрут ожидает наличие поля ввода email, содержащего адрес электронной почты, который пользователь хочет начать использовать.

Без защиты от CSRF вредоносный веб-сайт мог бы создать HTML-форму, которая указывает на маршрут /user/email вашего приложения и отправляет адрес электронной почты самого злоумышленника:

<form action="https://your-application.com/user/email" method="POST">
<input type="email" value="malicious-email@example.com">
</form>
 
<script>
document.forms[0].submit();
</script>

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

Чтобы предотвратить эту уязвимость, необходимо проверять каждый входящий запрос с методами POST, PUT, PATCH или DELETE на наличие секретного значения сессии, к которому вредоносное приложение не имеет доступа.

2. Предотвращение CSRF-запросов

Laravel автоматически генерирует CSRF-"токен" для каждой активной пользовательской сессии, управляемой приложением. Этот токен используется для проверки того, что аутентифицированный пользователь действительно является тем, кто отправляет запросы в приложение. Поскольку этот токен хранится в пользовательской сессии и изменяется каждый раз при её регенерации, вредоносное приложение не может получить к нему доступ.

CSRF-токен текущей сессии можно получить через сессию запроса или с помощью вспомогательной функции csrf_token:

use Illuminate\Http\Request;
 
Route::get('/token', function (Request $request) {
$token = $request->session()->token();
 
$token = csrf_token();
 
// ...
});

Каждый раз, когда вы определяете HTML-форму с методами "POST", "PUT", "PATCH" или "DELETE" в вашем приложении, вы должны включать скрытое поле CSRF _token в форму, чтобы промежуточное ПО защиты от CSRF могло проверить запрос. Для удобства вы можете использовать директиву Blade @csrf для создания скрытого поля с токеном:

<form method="POST" action="/profile">
@csrf
 
<!-- Equivalent to... -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>

Промежуточное ПО Illuminate\Foundation\Http\Middleware\ValidateCsrfToken, которое по умолчанию включено в группу промежуточного ПО web, автоматически проверяет, что токен в данных запроса совпадает с токеном, хранящимся в сессии. Когда эти два токена совпадают, мы знаем, что аутентифицированный пользователь является инициатором запроса.

2.0.1. CSRF-токены и SPA

Если вы создаёте SPA, которое использует Laravel в качестве API-бэкенда, вам следует обратиться к документации Laravel Sanctum для получения информации об аутентификации с вашим API и защите от CSRF-уязвимостей.

2.1. Исключение URI из защиты от CSRF

Иногда вы можете захотеть исключить набор URI из защиты от CSRF. Например, если вы используете Stripe для обработки платежей и используете их систему вебхуков, вам нужно будет исключить маршрут обработчика вебхуков Stripe из защиты от CSRF, так как Stripe не будет знать, какой CSRF-токен отправить вашим маршрутам.

Как правило, такие маршруты следует размещать за пределами группы промежуточного ПО web, которую Laravel применяет ко всем маршрутам в файле routes/web.php. Однако вы также можете исключить определённые маршруты, указав их URI в методе validateCsrfTokens вашего приложения в файле bootstrap/app.php:

->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
]);
})
lightbulb

Для удобства промежуточное ПО CSRF автоматически отключается для всех маршрутов при запуске тестов.

3. X-CSRF-TOKEN

Помимо проверки CSRF-токена как параметра POST-запроса, промежуточное ПО Illuminate\Foundation\Http\Middleware\ValidateCsrfToken, которое по умолчанию включено в группу web, также проверяет заголовок запроса X-CSRF-TOKEN. Например, вы можете сохранить токен в HTML-теге meta:

<meta name="csrf-token" content="{{ csrf_token() }}">

Затем вы можете настроить библиотеку, такую как jQuery, чтобы она автоматически добавляла токен во все заголовки запросов. Это обеспечивает простую и удобную защиту от CSRF для ваших приложений на основе AJAX, использующих устаревшие технологии JavaScript:

$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});

4. X-XSRF-TOKEN

Laravel сохраняет текущий CSRF-токен в зашифрованной cookie XSRF-TOKEN, которая включается в каждый ответ, сгенерированный фреймворком. Вы можете использовать значение этой cookie для установки заголовка запроса X-XSRF-TOKEN.

Эта cookie предоставляется главным образом для удобства разработчиков, так как некоторые JavaScript-фреймворки и библиотеки, такие как Angular и Axios, автоматически помещают её значение в заголовок X-XSRF-TOKEN для запросов с тем же источником.

lightbulb

По умолчанию файл resources/js/bootstrap.js включает библиотеку HTTP-запросов Axios, которая автоматически отправляет заголовок X-XSRF-TOKEN за вас.