Laravel: безпека застосунку
20 питань · ~20 хв · Версія v3.0
Увійдіть, щоб продовжити
CSRF і перевірка джерела, XSS поза екрануванням, ін'єкції в сирих запитах, шифрування й ротація APP_KEY, хешування, довірені проксі й хости - питання всіх рівнів, від junior до lead.
- За спробу
- 20
- У пулі
- 61
- Проходжень
- 0
- Середній бал
- -
- Пройшли на 70%+
- -
Питання для підготовки
21 питанняCSRF (Cross-Site Request Forgery) - це атака, коли сторонній сайт змушує браузер автентифікованого користувача надіслати небажаний запит на ваш застосунок, використовуючи його активну сесію (наприклад, прихована форма, що переказує гроші).
Як Laravel захищає: для кожної активної сесії генерується унікальний CSRF-токен. Middleware ValidateCsrfToken перевіряє цей токен для всіх «небезпечних» методів - POST, PUT, PATCH, DELETE. Запити без валідного токена відхиляються з кодом 419.
У формах додають директиву @csrf, яка вставляє прихований інпут із токеном:
<form method="POST" action="/profile">
@csrf
<input name="email" type="email">
<button>Зберегти</button>
</form>
Для AJAX токен передають у заголовку X-CSRF-TOKEN (зазвичай із <meta name="csrf-token">):
fetch('/profile', {
method: 'POST',
headers: { 'X-CSRF-TOKEN': token },
});
GET-запити токена не потребують (вони мають бути безпечними й не змінювати стан). Для stateless API на токенах (Sanctum) CSRF не застосовується.
Mass Assignment - це присвоєння групи атрибутів моделі з масиву (наприклад, Model::create($request->all())). Вразливість виникає, коли користувач підкидає неочікувані поля (скажімо, is_admin).
Захист - білий або чорний список у моделі:
protected $fillable = ['title', 'body']; // дозволено лише ці
// або
protected $guarded = ['id', 'is_admin']; // заборонено ці
Найкраща практика: не передавати $request->all(), а валідувати й передавати $request->validated().
- Паролі - лише одностороннє хешування (Bcrypt/Argon2):
Hash::make()/Hash::check(). Ніколи не шифрування й не власні алгоритми. - PII (двостороннє) -
Crypt::encryptString()або кастencryptedна атрибуті моделі:protected $casts = ['ssn' => 'encrypted']; - Ключі та секрети - у
.env/ секретних сховищах (AWS Secrets Manager, Vault), не в git. РотаціяAPP_KEYпотребує перешифрування. - Транзит - лише HTTPS/TLS.
- Логи - маскувати PII; уникати
dd()у проді. - Доступ - принцип найменших привілеїв, audit log (наприклад,
spatie/laravel-activitylog).
2FA вимагає двох факторів: «що знаю» (пароль) + «що маю» (код із застосунку/SMS). Найпоширеніше - TOTP (Time-based One-Time Password) сумісно з Google Authenticator.
У Laravel найпростіше через Fortify, який має 2FA з коробки:
- генерація секрету й QR-коду для прив'язки;
- перевірка 6-значного коду при вході;
- одноразові recovery codes на випадок втрати пристрою.
// Fortify вмикає features:
Features::twoFactorAuthentication(['confirm' => true]),
Під капотом - пакет pragmarx/google2fa. Важливо: зберігати секрет зашифрованим, давати recovery-коди, за бажанням «запам'ятати пристрій».
Докладніше в документації: Двофакторна автентифікація (Fortify)
CSP - HTTP-заголовок, що визначає, з яких джерел дозволено завантажувати ресурси (скрипти, стилі, зображення). Це потужний захист від XSS: навіть якщо зловмисник впровадить <script>, браузер не виконає його, якщо джерело не дозволене.
Content-Security-Policy: default-src 'self';
script-src 'self' https://cdn.example.com;
img-src 'self' data:;
У Laravel заголовок додають через middleware (вручну або пакетом на кшталт spatie/laravel-csp).
Практики:
- Уникати
'unsafe-inline'- використовувати nonce для інлайн-скриптів. - Спершу режим report-only (
Content-Security-Policy-Report-Only) зі збором звітів, щоб не зламати сайт.
Спершу почитати
Прочитати - ще не значить знати
20 питань, по одному на екран, ~20 хв. Після завершення - розбір кожної помилки з посиланням на питання.