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/*', ]);})
Для удобства промежуточное ПО 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
для запросов с тем же источником.
По умолчанию файл resources/js/bootstrap.js
включает библиотеку HTTP-запросов Axios, которая
автоматически отправляет заголовок X-XSRF-TOKEN
за вас.