1. Основы
  2. Защита CSRF

Присоединяйся к нашему Telegram сообществу @webblend!

Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.

Введение

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

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

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

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

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

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

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

Предотвращение 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 могло проверить запрос. Для удобства вы можете использовать директиву @csrf Blade для генерации скрытого поля ввода токена:

<form method="POST" action="/profile">
@csrf
 
<!-- Эквивалентно... -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>

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

CSRF-токены и SPA

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

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

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

Обычно вы должны размещать такие маршруты вне группы промежуточного ПО web, которую применяет App\Providers\RouteServiceProvider ко всем маршрутам в файле routes/web.php. Однако вы также можете исключить маршруты, добавив их URI в свойство $except промежуточного ПО VerifyCsrfToken:

<?php
 
namespace App\Http\Middleware;
 
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
 
class VerifyCsrfToken extends Middleware
{
/**
* URI, которые следует исключить из проверки CSRF.
*
* @var array
*/
protected $except = [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
];
}

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

X-CSRF-TOKEN

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

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

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

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

X-XSRF-TOKEN

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

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

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