12 лучших практик безопасности Laravel на 2023 год
Безопасность — обширная тема, и данная статья не охватывает её полностью. Да и возможно ли это вообще?
Тем не менее я хочу дать как можно больше полезных практик, советов и рекомендаций, которые помогут консолидировать ваши веб-приложения Laravel.
Не отслеживайте .env
-файл
Ваш .env
-файл содержит конфиденциальную информацию.
Пожалуйста, не отслеживайте его!
Убедитесь, что он добавлен в .gitignore
.
Чаще всего утечки данных происходят внутри компании.
Менеджер паролей — лучшее решение для обмена учётными данными.
Если вы хотите, чтобы члены команды имели доступ к закрытому набору конфиденциальной информации, используйте менеджер паролей с проверенной репутацией надёжной защиты.
- Менеджер паролей: Какой выбрать?
- Менеджеры паролей: Корпоративные платформы
- Безопасный способ использования переменных .env в Laravel
Поддерживайте Laravel в актуальном состоянии
Поддерживая Laravel в актуальном состоянии, вы сможете быть в курсе последних обновлений системы безопасности.
Убедитесь, что используете версию Laravel, для которой все ещё выпускаются исправления, и все будет в порядке.
Если вы никогда не обновляли проект Laravel, прочитайте Laravel 10: Руководство по обновлению, которое подскажет вам, как это сделать.
Поддерживайте в актуальном состоянии базовые и сторонние пакеты
Доступ к десяткам пакетов из официальной экосистемы Laravel и тысячам пакетов сообщества — то, что облегчает нашу работу.
Но чем больше пакетов вы используете, тем больше точек отказа может возникнуть.
Регулярное выполнение composer update
значительно повышает безопасность кодовой базы.
Отключите отладочные сообщения в production
Убедитесь, что эти две переменные окружения корректно установлены в production.
APP_ENV=production
APP_DEBUG=false
Не стоит допускать утечки информации об архитектуре или конфигурации приложения. Обычно отладочные сообщения содержат много таких сведений.
Не передавайте конфиденциальную информацию средствам мониторинга ошибок
Если говорить о конфиденциальной информации в отладочных сообщениях, то мы ещё не избавились от неё.
Если вы используете инструмент мониторинга ошибок, то они должны быть и там.
В PHP 8.2 появился новый атрибут #SensitiveParameter, позволяющий скрыть любую информацию из трассировки стека (которая отправляется в средства мониторинга ошибок).
function something(
#[\SensitiveParameter]
$top_secret_parameter,
$who_cares_parameter,
) {
throw new \Exception('Whoops, something bad happended!');
}
Ограничение частей приложения с помощью политик
Политики в Laravel — это как вышибалы в ночном клубе, препятствующие доступу людей в запрещённые зоны.
Давайте рассмотрим реальный пример использования политики:
// app/Policies/PostPolicy.php
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
// app/Http/Controllers/PostController.php
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// ...
}
Как видите, с их помощью очень легко проверить наличие разрешения, прежде чем разрешить пользователю что-либо делать.
Обязательно ознакомьтесь с документацией, поскольку о политиках можно многое узнать.
Защита форм от подделки межсайтовых запросов (CSRF)
Возможно, вам захочется использовать в своих формах директиву @csrf
Blade.
<form method="POST" action="{{ route('register') }}">
@csrf
<p>
<label for="name">First Name</label>
<input type="text" id="name" name="name" value="{{ old('name') }}" required />
</p>
…
</form>
Данная директива генерирует скрытое поле ввода, содержащее CSRF-токен, автоматически включаемый при отправке формы.
Этот токен подтверждает, что форма отправляется из вашего приложения, а не от третьего лица.
Проверка осуществляется с помощью middleware VerifyCsrfToken
, которое Laravel использует по умолчанию для всех ваших веб-маршрутов.
Подробнее о защите от CSRF можно узнать из документации Laravel.
- Как исправить ошибку Fix 419 Page Expired/CSRF token mismatch
- CSRF: Подделка межсайтовых запросов
- CSRF: Как предотвратить уязвимость
- CSRF: Обход защиты основанной на Referer
- CSRF: Обход проверки токена
Валидация вводимых пользователем данных
Валидация в Laravel имеет решающее значение для обеспечения безопасности приложения.
Правила валидации многочисленны и помогут вам с лёгкостью обеззараживать данные, которые отправляют ваши пользователи. Ведь вы знаете, как это делается, верно? Никогда не доверяйте вводимым пользователями данным.
use Illuminate\Http\Request;
class PostController extends Controller
{
function store(Request $request)
{
$validated = $request->validate([
'user_id' => 'required|exists:users,id',
'title' => 'required|string|min:3|max:255',
'content' => 'required|string|min:3',
'published' => 'sometimes|boolean'
]);
Post::create($validated);
//
}
}
Подробнее о валидации в Laravel можно узнать из официальной документации.
- Валидация в Laravel: Как полностью настроить формат сообщений об ошибках
- Laravel: Условная валидация
- Laravel: Валидация данных приложения
- Laravel: Поговорим о запросах формы / Form Request
- Тестирование правил валидации Laravel с помощью Pest PHP
Будьте осторожны с загружаемыми файлами
Как мы уже видели, пользовательскому вводу никогда нельзя доверять. Это относится и к загружаемым файлам. Вот несколько рекомендаций:
Проверьте MIME-тип файла (в Laravel для этого есть соответствующие правила валидации).
$request->validate([
'file' => 'required|mimes:gif,jpeg,png,webp',
]);По возможности не делайте загруженные файлы общедоступными (например, с помощью драйвера локального файла).
Загружайте файлы на другой сервер. Если хакер обойдёт вашу защиту, он не сможет выполнить несанкционированный код и получить доступ к конфиденциальной информации.
Делегируйте загрузку файлов сторонним сервисам, которые известны своей безопасностью (то есть никогда не допускают утечки данных).
Шифрование полезной нагрузки в заданиях
Когда вы отправляете задание, его полезная нагрузка сохраняется в базе данных, Redis или другой системе, которую вы указали Laravel использовать с помощью переменной окружения QUEUE_DRIVER
.
Полезная нагрузка может содержать конфиденциальную информацию, которую может просмотреть любой ваш сотрудник и потенциально использовать её не по назначению. Как я уже говорил в начале статьи, утечки часто происходят по вине сотрудников.
К счастью, в Laravel предусмотрен контракт Illuminate\Contracts\Queue\ShouldBeEncrypted
, который автоматически шифрует полезную нагрузку. Чтобы убедиться, что никто не сможет их расшифровать, убедитесь, что ключ Laravel APP_KEY
, определённый в вашем .env, недоступен никому, кроме нескольких доверенных лиц.
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
class SomeJob implements ShouldQueue, ShouldBeEncrypted
{
//
}
Пишите тесты для выявления рисков безопасности
К сожалению, тестирование является обширной и малоизвестной темой среди разработчиков.
Автоматическое тестирование нескольких сценариев на предмет потенциальных нарушений безопасности — отличный способ убедиться, что они остаются закрытыми.
Laracasts предлагает бесплатные курсы по тестированию, которые помогут вам начать работу. Один из них посвящён PHPUnit, отраслевому стандарту, а другой — Pest, лучшему фреймворку для тестирования на этой планете, который модернизирует и упрощает тестирование на PHP.
- PHP Testing Jargon
- Pest From Scratch
- Laravel: Три вещи, которые нужны для TDD
- Laravel: Как начать тестировать приложение
- Laravel: Как тестировать invokable правила
- Тестирование конечных точек JSON:API с PestPHP
- Laravel: Руководство по тестированию с Pest
- Laravel: Всё, что вы можете протестировать в приложении
- Архитектурный плагин Pest
- Тестирование правил валидации Laravel с помощью Pest PHP
Проводите регулярные аудиты безопасности
Эта практика является одной из самых эффективных и должна быть обязательной для всех, кто серьёзно относится к безопасности. Внешняя обратная связь может открыть глаза.
Как вы понимаете, проведение аудита безопасности — дело не бесплатное. Возможно, это стоит делать только предприятиям, поскольку возможные штрафы обойдутся ещё дороже! Но за сохранение хорошей репутации и доверия пользователей платить не стоит.