Авторизация отвечает на вопрос «что тебе можно». Нарушение контроля доступа первое место в OWASP Top 10, а три пункта из десяти в API Top 10 про авторизацию. Причина простая: сканер не знает бизнес-правил, и такие ошибки находят люди.
IDOR и BOLA
IDOR (Insecure Direct Object Reference) и BOLA (так это называют в API) одно и то же: сервер берёт идентификатор объекта из запроса и не проверяет, имеет ли пользователь право на этот объект.
GET /api/invoices/1002 → свой счёт
GET /api/invoices/1003 → чужой счёт, а сервер отдал
Защита:
- Проверка в каждом обработчике: объект принадлежит пользователю, его организации или пользователь имеет нужную роль.
- Лучше встроить ограничение в запрос:
WHERE id = ? AND owner_id = ?или репозиторий, который всегда добавляет фильтр по арендатору. - UUID вместо последовательных id затрудняет перебор, но это не защита: идентификаторы утекают в ссылках, логах, письмах.
- Ответ «не найдено» вместо «запрещено» для чужих объектов, чтобы не подтверждать их существование.
Уровни авторизации в API
- Объект (BOLA): доступ к конкретной записи.
- Свойство объекта: какие поля можно читать и писать. Mass assignment: клиент присылает
{"role": "admin"}, а код делаетuser.update(req.body). Защита: явные DTO и allowlist полей на запись, отдельные схемы ответа. - Функция (BFLA): кто может вызывать операцию. Админские эндпоинты должны проверять роль на сервере, а не прятаться в интерфейсе.
Модели доступа
- RBAC (Role-Based Access Control): права назначаются ролям, роли пользователям. Просто и понятно, но не выражает «свой документ» и «документ своего отдела» без взрыва числа ролей.
- ABAC (Attribute-Based): решение по атрибутам субъекта, объекта, действия и контекста:
user.department == doc.department AND action == "read" AND time in work_hours. Гибко, сложнее отлаживать. - ReBAC (Relationship-Based): права следуют из связей в графе: «редактор папки может редактировать документы в ней». Подход Google Zanzibar, реализации OpenFGA, SpiceDB.
- ACL: список доступа у каждого объекта.
На практике комбинируют: роли для функций, владение и атрибуты для объектов.
Принципы
- Запрет по умолчанию: если правило не нашлось, доступ закрыт.
- Проверка на сервере на каждый запрос. Скрытая кнопка в интерфейсе не защита.
- Централизация: политика в одном месте (middleware, сервис политик, библиотека вроде Casbin, OPA), а не копипаста
ifпо контроллерам. - Минимальные привилегии для пользователей, сервисов и учёток.
- Мультиарендность: каждый запрос к данным фильтруется по арендатору. Помогают Row-Level Security в PostgreSQL и обязательный tenant-контекст в слое данных.
- Тесты на доступ: два пользователя, две организации, проверка, что чужое недоступно. Это лучший регресс для BOLA.
Частые ловушки
- Проверка прав в списке, но не в детальном просмотре или в экспорте.
- Проверка при чтении, но не при обновлении и удалении.
- Доверие к
userIdилиroleиз тела запроса или из JWT без проверки подписи. - Вложенные ресурсы:
/orgs/1/projects/55проверяет доступ к организации 1, но не то, что проект 55 в ней. - Пакетные и GraphQL-запросы, где проверка на уровне поля забыта.
- Гонки: проверка и действие в разных транзакциях (TOCTOU).
- Непрямые пути: файлы по прямым ссылкам, вебхуки, фоновые задачи.
Что спросят на собесе
- Что такое IDOR и как его найти и исправить.
- Чем BOLA отличается от BFLA.
- RBAC или ABAC: когда что.
- Как защитить мультиарендное приложение от утечки данных между клиентами.
- Защищают ли UUID от IDOR.
- Что такое mass assignment.