Разграничение доступа в веб-приложении: где оно ломается
Пользователь вошёл в систему — но это ещё не значит, что ему можно открыть любой объект или выполнить любое действие. Разбираем, где теряются проверки доступа: в API, многопользовательских данных, кэше и фоновых задачах.

Вход в систему — не разрешение на всё
Пользователь может успешно войти в приложение и всё равно не иметь права открыть конкретный заказ, изменить чужой профиль или скачать файл из соседней организации. Ошибка обычно не в форме входа: проверка доступа пропущена в отдельном маршруте, фоновой задаче или слое кэширования. Результат — утечка данных или действие от имени не того пользователя.
Разбор относится к веб-приложениям независимо от языка и фреймворка. В качестве проверочного ориентира используем OWASP ASVS 5.0.0; конкретные средства реализации зависят от стека. Здесь важен не выбор библиотеки авторизации, а то, чтобы один и тот же запрет действовал во всех путях к данным.
Три проверки, которые нельзя смешивать
Сначала установите, кто обращается к приложению, затем — что этому субъекту разрешено делать и с каким объектом. Это разные вопросы, и ответ на первый не решает два остальных.
- Аутентификация: приложение проверило личность пользователя или другого клиента.
- Авторизация: приложение решило, разрешено ли этому субъекту конкретное действие.
- Область данных: приложение проверило, относится ли запрошенный объект к организации, проекту или другому пространству, доступному субъекту.
Типичная ошибка — проверить только роль, например «менеджер», но не принадлежность заказа организации пользователя. Или проверить доступ к странице, но забыть проверить его в API-запросе, который возвращает данные. Скрытая кнопка не является контролем доступа: маршрут можно вызвать напрямую.
Термин: IDOR (Insecure Direct Object Reference) — уязвимость, при которой приложение открывает объект по его идентификатору, но не проверяет, вправе ли запросивший пользователь работать именно с этим объектом.
Где проверки чаще всего теряются
Идентификатор объекта принимают за доказательство права
Запрос вида «откройте заказ с таким номером» сообщает приложению, какой объект ищут, но ничего не говорит о праве пользователя его видеть. Случайный или длинный идентификатор не заменяет авторизацию: его можно перехватить из ссылки, лога или интерфейса. Проверка должна связывать пользователя, действие и конкретный объект.
Особенно опасно, когда список заказов уже отфильтрован по организации, а карточка отдельного заказа загружается по идентификатору без того же ограничения. Список выглядит безопасным, но прямой запрос к карточке пересекает границу между клиентами.
Роль слишком широкая
«Администратор» часто начинает означать сразу несколько разных полномочий: управлять пользователями, просматривать финансовые сведения и менять настройки. Позже роли разрастаются, а исключения добавляются по одному. В результате разработчики не могут точно ответить, почему доступ разрешён, и опасаются менять проверку.
Проверяйте не только роль, но и контекст: к какой организации относится пользователь, какое действие выполняет, в каком состоянии находится объект. Например, право редактировать черновик не обязательно означает право менять уже отправленный документ.
Одинаковая проверка не покрывает все пути
Доступ к одному объекту может проходить через веб-страницу, API, экспорт, поиск, уведомление и фоновую задачу. Если проверка встроена только в обработчик страницы, остальные пути могут обходить её. Централизованное решение снижает риск расхождений, но только если каждый путь действительно обращается к нему и передаёт правильный контекст.
Есть и обратная ловушка: слишком общая проверка в одном месте может разрешить действие, которое конкретный маршрут не должен поддерживать. Важно проверять не абстрактный факт «пользователь имеет доступ», а конкретное действие над конкретным объектом.
Кэш сохраняет ответ для не того пользователя
Даже корректная проверка на первом запросе не спасает, если персональный ответ попадает в общий кэш, а следующий пользователь получает его без повторной авторизации. Риск появляется в кэше приложения, прокси и CDN. Для чувствительных данных проверьте, по каким признакам кэш разделяет ответы и может ли вообще хранить их совместно.
Отдельно проверьте смену роли и отзыв доступа. Если решение об авторизации или ответ кэшируются дольше, чем действует право пользователя, интерфейс может продолжить показывать уже запрещённые данные.
Фоновая задача теряет исходного субъекта
Экспорт или отправка уведомления часто запускаются через очередь. К моменту выполнения задачи пользовательский запрос уже закончился, а задача работает от системной учётной записи с широкими правами. Если в задании нет явной связи с пользователем, организацией и объектом, система может обработать данные вне исходных границ доступа.
Не передавайте задаче только идентификатор объекта и не считайте запуск пользователем достаточным разрешением. Определите, какие права проверяются при постановке задачи и при её выполнении, а также что происходит, если доступ отозвали между этими моментами.
Что проверять в архитектуре
| Подход | Что даёт | Цена и ограничение |
|---|---|---|
| Проверки в каждом маршруте | Можно учитывать специфику конкретного действия. | Легко забыть один маршрут; правила со временем расходятся. |
| Общий слой авторизации | Единые правила для разных частей приложения. | Нужно дисциплинированно проводить через него все запросы и контекст объектов. |
| Ограничение выборки по области доступа | Чужие записи не попадают в обычный путь чтения. | Не заменяет проверку действий вроде изменения, экспорта или удаления. |
Это не взаимоисключающие варианты. Надёжная схема обычно сочетает общие правила авторизации с ограничением выборки данных и проверкой конкретного действия. Критерий простой: если в маршруте, задаче или экспорте можно получить объект, не передавая сведения о субъекте и его области доступа, граница уже уязвима.
Проверка доступа считается общей только тогда, когда её нельзя случайно пропустить на другом пути к тому же объекту.
Как проверить систему до инцидента
Проверяйте не только роли, но и границы между пользователями и организациями. Для каждого действия составьте матрицу «субъект — действие — объект — ожидаемый результат». Например: пользователь организации А запрашивает заказ организации Б; обычный сотрудник пытается изменить настройку администратора; пользователь теряет доступ, пока экспорт стоит в очереди.
- Выберите реальные чувствительные объекты: заказы, документы, файлы, профили и настройки.
- Для каждого объекта перечислите пути чтения и изменения: API, веб-интерфейс, экспорт, поиск и фоновые задачи.
- Проверьте разрешённый сценарий и отказ для другого пользователя с тем же типом учётной записи.
- Повторите тест после смены роли, отзыва доступа и перемещения объекта между организациями.
- Проверьте ответы кэша и журналы: отказ не должен раскрывать содержимое объекта, а журнал должен позволять понять, кто, что и над чем пытался сделать.
Измеряйте полноту покрытия: сколько путей к чувствительным данным имеют проверяемый сценарий отказа, сколько тестов подтверждают изоляцию организаций и сколько запросов всё ещё обходят общий слой авторизации. Универсальных цифр для этих показателей нет; важна динамика покрытия конкретных маршрутов, а не один процент без списка проверок.
Что ломается на границах
- Идентификатор угадан или получен из другого места. Скрытие ссылки не помогает: сервер обязан самостоятельно проверить право на объект.
- Пользователя удалили или отключили. Проверьте, как это влияет на активные сессии, очереди и уже выданные ссылки на файлы.
- Роль изменилась во время сессии. Решение, основанное на старых данных в сессии или кэше, может сохранять отменённый доступ.
- Объект переместили между организациями. Убедитесь, что проверка использует актуальную принадлежность объекта, а не старое значение из запроса.
- Ошибка при проверке доступа. Если сервис авторизации недоступен, для чувствительных операций безопаснее отказать, а не молча разрешить действие.
Смежная тема — защита от CSRF и управление сессиями: они важны, но не заменяют проверку полномочий на объект.
Что делать дальше
Начните с одного чувствительного типа данных и проследите его путь от запроса до базы, кэша и очереди. Добавьте тесты на доступ между двумя пользователями и двумя организациями, затем проверьте все альтернативные способы получить тот же объект. Для формальной проверки требований используйте OWASP ASVS 5.0.0, а в эксплуатации следите за отказами авторизации, ошибками кэширования и задачами, выполняемыми с системными правами.
Задачи: математика, физика, химия: Разбор задачи по шагам с проверкой и похожей задачей
Спросить за 10 ₽Источники: OWASP Authorization Cheat Sheet, OWASP Application Security Verification Standard
Частые вопросы
Если пользователь вошёл в систему, разве этого недостаточно?
Достаточно ли скрыть кнопку или ссылку в интерфейсе?
Случайные идентификаторы защищают от доступа к чужим данным?
Что проверить, если после отзыва доступа данные всё ещё видны?
Как тестировать изоляцию данных между организациями?
Какие рекомендации по версии использовать?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.