ТестированиеТестирование безопасностиИнженер по тестированию безопасности

Представьте ресурс, доступный любому аутентифицированному пользователю по идентификатору в запросе. Как про...

Представьте ресурс, доступный любому аутентифицированному пользователю по идентификатору в запросе. Как проверить, что доступ к чужому объекту запрещён?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Нужно проверить авторизацию на уровне объекта: отправить запрос к объекту, принадлежащему другому пользователю, сохранив действительную аутентификацию, и убедиться, что сервер отказывает в доступе. Наличие входа в систему подтверждает только личность пользователя, но не его право работать с каждым конкретным объектом.

Исторический контекст

В ранних веб-приложениях разработчики часто считали достаточной проверку факта входа пользователя. Идентификатор объекта передавался клиентом, а сервер напрямую использовал его без проверки владельца или разрешений.

Так возник класс ошибок, известный как IDOR, а в современной терминологии BOLA — нарушение авторизации на уровне объекта. Подход к тестированию сформировался как реакция на необходимость проверять не только аутентификацию, но и каждое решение о доступе.

Постановка проблемы

Пусть пользователь имеет право просматривать объект с идентификатором A. Если он заменяет этот идентификатор на B, принадлежащий другому пользователю, сервер должен заново проверить разрешение на объект B.

Неверная реализация возвращает чужие данные, позволяет изменить объект или удалить его. Это может привести к утечке персональных данных, несанкционированным изменениям и нарушению изоляции между клиентами.

Подробное решение

Тест строится на нескольких учетных записях с различными ролями и наборами объектов. Для каждой операции проверяют как минимум четыре случая: доступ владельца разрешён, доступ постороннего пользователя запрещён, доступ пользователя с недостаточной ролью запрещён, доступ к несуществующему объекту обрабатывается безопасно.

Важно сохранять действительную сессию атакующего пользователя. Иначе тест будет проверять аутентификацию, а не авторизацию. Также следует проверять не только чтение, но и изменение, удаление, экспорт, скачивание файлов и косвенные операции, например добавление участника к объекту.

Проверка должна выполняться на сервере для каждого запроса и каждого объекта. Скрытие идентификаторов в интерфейсе, последовательная нумерация, случайные идентификаторы или отключение кнопки в клиенте не заменяют серверную проверку разрешений.

Безопасный отказ должен не раскрывать лишние сведения. В некоторых системах используют единый ответ для отсутствующего и недоступного объекта, чтобы не позволять угадывать существование данных; однако точный статус может быть оправдан внутренним API, если он не создаёт нежелательного раскрытия информации.

Автоматизация полезна для перебора матрицы ролей и объектов, но сама по себе не доказывает корректность модели доступа. Нужно заранее определить владельцев, участников, границы организаций и наследование разрешений.

Ситуация из практики

В многоклиентском сервисе пользователь мог просматривать документы своей организации. При ручной проверке интерфейс не показывал чужие документы, поэтому первоначально рассматривались два варианта: считать интерфейс достаточной защитой или проверять серверную авторизацию через две тестовые организации.

Первый вариант был быстрее, но не защищал от прямых запросов и не проверял изоляцию данных. Второй требовал подготовки тестовых данных, зато позволял установить, что решение о доступе принимается сервером.

Выбрали второй вариант и проверили чтение, изменение и скачивание документов. Чтение оказалось защищено, но операция скачивания использовала отдельный обработчик без проверки организации. После добавления общей серверной проверки разрешений и регрессионных тестов скачивание чужих документов стало невозможным, а разрешённые операции сохранились.

Что кандидаты часто упускают

  1. Допустимо ли защищать объект только непредсказуемым идентификатором?

Нет. Случайный или длинный идентификатор снижает вероятность угадывания, но не является проверкой полномочий. Идентификатор может попасть в журналы, историю браузера, ссылки, сообщения, резервные копии или ответы другого API. Если полученный идентификатор принимается без проверки права доступа, ошибка сохраняется.

  1. Достаточно ли проверить запрет чтения чужого объекта?

Нет. Для каждой операции может использоваться отдельный путь обработки и отдельная политика доступа. Объект может быть защищён при просмотре, но доступен через скачивание, поиск, экспорт, массовую операцию, изменение или удаление. Полноценная проверка строит матрицу субъектов, объектов и действий.

  1. Как отличить ошибку авторизации от намеренного раскрытия существования объекта?

Нужно разделять право получить содержимое и право узнать факт существования. Сервер может скрывать содержимое, но выдавать различающиеся статусы, размеры ответа или сообщения, по которым можно перечислять чужие объекты. Поэтому проверяют не только данные в ответе, но и статус, тело, заголовки, время обработки и побочные эффекты. Требуемое поведение определяется моделью угроз и контрактом API, но оно должно быть единообразным для всех способов обращения к объекту.