Бухгалтер із правами лише для читання міг скасовувати інвойси та видаляти історію платежів у інструменті для ведення бухгалтерського обліку з відкритим кодом Akaunting, що створювало ризик прихованої втрати даних для малого бізнесу. Помилку було виправлено у версії 3.2.0, але сама помилка — прив'язка перевірки дозволів до жорстко заданого списку назв методів — все ще загрожує будь-якій системі, що покладається на керування доступом на основі ролей.

Як помилка просочилася в систему

API Akaunting перевіряє права користувача, звертаючись до білого списку (allowlist) назв методів. Список охоплював звичні операції CRUD — create, read, update, delete — але не враховував кілька кінцевих точок (endpoints), що змінюють статус:

  • markSent
  • markCancelled
  • markReceived

Оскільки ці обробники не були у списку, фреймворк ніколи не викликав процедуру перевірки дозволів під час їх виконання. Користувач із роллю «тільки для читання» міг надіслати простий GET-запит до кінцевої точки markCancelled, і система сприймала б це як легітимну зміну стану.

Скасування інвойсу — це не просто позначення документа як недійсного; це також видаляє всі записи про платежі, пов'язані з цим інвойсом. Результат: користувач без прав на редагування може стерти фінансовий слід транзакції.

Що показало тестування

Уразливість була виявлена в офіційному Docker-образі Akaunting:

  • Стандартний PUT-запит для оновлення інвойсу повертав 403 Forbidden, що підтверджувало захищеність звичайного шляху оновлення.
  • GET-запит до кінцевої точки скасування пройшов успішно без помилки авторизації, що виявило прогалину.

Чому це важливо

Фінансову звітність можна змінити без чіткого аудиторського сліду, що ускладнює виявлення шахрайства та виправлення чесних помилок.

Виправлення

Версія 3.2.0 розширює карту дозволів, включаючи раніше пропущені дії зі зміною статусу. Починаючи з цього релізу, будь-який запит, що змінює стан документа — чи то позначка «надіслано», «скасовано» або «отримано» — має проходити таку ж перевірку ролі, як і стандартне оновлення. Це відновлює очікування, що роль «тільки для читання» дійсно не може змінювати дані.

Уроки для розробників

  • Ніколи не прирівнюйте назви методів до безпеки. Додавання нової кінцевої точки не означає автоматичного успадкування захисту; перевіряйте кожен публічний метод на наявність побічних ефектів.
  • Білі списки настільки повні, наскільки повний сам список. Статичний список «правильних» дієслів залишає двері відкритими для помилок.
  • Відокремлюйте намір від HTTP-методу. GET призначений лише для читання, але в цьому випадку він змінив стан. Обмежуйте мутації методами POST, PUT, DELETE, PATCH.
  • Автоматизуйте перевірку охоплення дозволів. Інструменти статичного аналізу можуть позначати методи контролерів, у яких відсутній виклик авторизації, виявляючи прогалини ще до релізу.
  • Тестуйте з обліковими записами з мінімальними привілеями. Тестування на основі Docker використовувало користувача з правами лише для читання; відтворення таких сценаріїв у CI-конвеєрах дозволяє виявити подібні проблеми на ранніх етапах.

На що звернути увагу далі

Спільнота Akaunting уже випустила виправлену версію. Адміністраторам слід перевірити версію свого екземпляра та вчасно застосувати оновлення.

Для розробників, які створюють будь-яку систему на основі ролей, висновок очевидний: модель дозволів, яка залежить від запам'ятовування кожної можливої дії, є вразливою за своєю природою. Чітко оголошуйте, які операції змінюють стан, впроваджуйте перевірки на рівні фреймворку та регулярно проводьте аудит коду. Тільки тоді можна бути впевненим, що мітка «тільки для читання» справді забезпечить цілісність фінансових записів.