Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Junior: питання на співбесіді з теми «Безпека»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

3 питання

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 не застосовується.

Докладніше в документації: CSRF-захист

Mass Assignment - це присвоєння групи атрибутів моделі з масиву (наприклад, Model::create($request->all())). Вразливість виникає, коли користувач підкидає неочікувані поля (скажімо, is_admin).

Захист - білий або чорний список у моделі:

protected $fillable = ['title', 'body']; // дозволено лише ці
// або
protected $guarded = ['id', 'is_admin']; // заборонено ці

Найкраща практика: не передавати $request->all(), а валідувати й передавати $request->validated().

Докладніше в документації: Mass Assignment

Eloquent і конструктор запитів передають значення окремо від SQL - прив'язками параметрів (prepared statements). База отримує WHERE email = ? і значення поруч, тож введення користувача ніколи не стає частиною команди.

User::where('email', $request->email)->first();   // безпечно

Де захист перестає працювати:

  1. Сирі методи з підставленим значенням:
User::whereRaw("email = '{$request->email}'")->first();     // ін'єкція
User::whereRaw('email = ?', [$request->email])->first();    // безпечно

Те саме для selectRaw, orderByRaw, DB::statement(), DB::raw().

  1. Назви колонок з введення. PDO не прив'язує назви колонок:
Post::orderBy($request->input('sort'))->get();   // небезпечно

Колонку беруть зі списку дозволених:

$sort = in_array($request->sort, ['title', 'created_at'], true) ? $request->sort : 'created_at';
  1. Ключі масиву в update() з $request->all() - це вже масове присвоєння, від якого захищають $fillable і validated().

Правило: усе, що прийшло від користувача, - тільки значеннями через прив'язки, ніколи не частиною SQL.

Докладніше в документації: Сирі вирази