InvoiceShelf випустила патч для CVE-2026-55610 — критичної вразливості, яка дозволяла будь-якому власнику (Owner) однієї компанії захоплювати облікові записи користувачів іншої компанії. Вразливість із оцінкою 8.7 за шкалою CVSS виникла через відсутність перевірки межі тенанта (tenant-scope check) у коді додатка на Laravel.
Як працювала вразливість
InvoiceShelf — це SaaS-інструмент на базі Laravel, який дозволяє компаніям керувати користувачами, рахунками-фактурами та налаштуваннями з єдиної панелі керування. Платформа зчитує спеціальний заголовок (custom header) для ідентифікації тенанта. Коли Власник (Owner) запитує запис користувача, код перевіряє лише одне: «Чи є запитувач Власником своєї компанії?»
Він ніколи не перевіряє, чи належить цільовий користувач до того самого тенанта. Неявне прив'язування моделі до маршруту (implicit route-model binding) у Laravel пов'язує ID користувача з рядком у глобальній таблиці користувачів, а політика авторизації схвалює запит лише на основі ролі запитувача.
Таким чином, зловмисник міг:
- Передати будь-який числовий ID користувача в URL-адресі запиту.
- Отримати повний запис користувача, включаючи email.
- Виконати оновлення, яке перезапише email та пароль жертви і навіть перепризначить обліковий запис компанії зловмисника як super-admin.
На практиці зловмисний Власник перетворив інструмент управління компанією на універсальну зброю для захоплення облікових записів. Для цього не було потрібно жодних привілеїв, окрім ролі «Owner».
Хто постраждав
Під загрозою опинився кожен клієнт InvoiceShelf, який використовував версію до 2.4.1. Оскільки вразливість міститься в основному шляху обробки запитів, будь-який тенант міг стати ціллю для Власника будь-якого іншого тенанта, незалежно від розміру чи рівня безпеки. Наслідки включають втрату конфіденційності (адреси електронної пошти) та втрату цілісності (несанкціоновані зміни паролів, підвищення привілеїв до super-admin).
Патч
Розробники випустили версію 2.4.1, додавши явну перевірку тенанта перед будь-якою операцією читання або запису запису користувача. Виправлення обмежує область запиту (scopes the query) ідентифікатором активної компанії, змушуючи Laravel повертати лише ті рядки, які належать тенанту запитувача.
Чого мають навчитися розробники
- Ніколи не покладайтеся на глобальні первинні ключі в багатоорендарних (multi-tenant) застосунках.
- Застосовуйте фільтр тенанта до кожного пошуку в базі даних, а не лише до дій видалення або створення.
- Зробіть так, щоб політики авторизації перевіряли як роль виконавця, так і належність цільового об'єкта до тенанта.
- Ставтеся до неявних функцій фреймворка, таких як route-model binding, як до зручних інструментів, які можуть приховувати прогалини в безпеці, якщо ви не додасте явне обмеження області (explicit scoping).
Погляд у майбутнє
Цей інцидент демонструє ширший ризик для будь-якого SaaS-сервісу, що використовує спільні таблиці. Аудити безпеки мають перевіряти всі кінцеві точки (endpoints), які приймають ідентифікатори, і підтверджувати, що обмеження області тенанта застосовується одноманітно.
Висновок: одна пропущена перевірка тенанта може перетворити привілейовану роль користувача на універсальний бекдор. Належне обмеження області (scoping) не є опціональним; це основа ізоляції даних у будь-якій багатоорендарній системі.
