Вертикальне підвищення привілеїв - звичайний користувач отримує можливості вищої ролі: адміністратора, модератора, менеджера.
Приклади:
- адмінка доступна за адресою
/admin, і перевіряється лише вхід, а не роль; - ендпойнт
POST /users/7/roleне перевіряє, хто змінює роль; - поле
is_adminможна передати у формі профілю (масове призначення); - роль зберігається на клієнті (у cookie без підпису, у
localStorage) - і її можна змінити.
Горизонтальне підвищення привілеїв - користувач отримує доступ до даних чи дій іншого користувача того самого рівня.
Приклади:
/invoices/1041- змінив число в адресі й бачиш чужий рахунок;PATCH /addresses/88змінює адресу іншого клієнта;- завантаження файлу за прямим посиланням без перевірки власника.
Горизонтальні вразливості трапляються частіше: перевірку ролі зазвичай пам'ятають (адмінка - очевидна мішень), а перевірку власності конкретного запису забувають у кожному новому ендпойнті.
Як захищатися:
Від вертикального:
- маршрути адмінки - в окремій групі з перевіркою ролі на рівні групи (middleware, політики);
- зміна ролей і прав - окремі ендпойнти з суворою авторизацією й журналом аудиту;
- роль - на сервері, а не в даних від клієнта.
Від горизонтального:
- пошук через власника:
$request->user()->invoices()->findOrFail($id)- чужий запис просто не знайдеться; - політики з перевіркою
$invoice->user_id === $user->id(чи належності до команди/організації); - обмеження вкладених маршрутів (
scopeBindings) - дочірній запис має належати батьківському.
Комбінований випадок: менеджер однієї компанії (рівень «менеджер» - вертикально все гаразд) бачить дані іншої компанії (горизонтально - ні). У багатоорендних застосунках перевірка належності до орендаря (tenant) потрібна для кожної ролі, включно з адміністраторами клієнтів.
Тест-матриця: для кожного ендпойнта - запит від анонімного користувача, від звичайного користувача-власника, від іншого користувача того самого рівня й від нижчої ролі. Очікувані відповіді - явно в тестах.