ТестированиеОсновы тестированияИнженер по тестированию

Пользователь меняет идентификатор записи в адресе и видит чужие данные. Какой механизм тестирования должен ...

Пользователь меняет идентификатор записи в адресе и видит чужие данные. Какой механизм тестирования должен выявить эту проблему?

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

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

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

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

По мере распространения веб-сервисов доступ к объектам стали часто запрашивать по идентификаторам из URL, параметров или тела запроса. Это упростило построение интерфейсов, но создало риск: клиент может изменить идентификатор и обратиться к объекту, который ему не принадлежит.

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

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

Пусть пользователь имеет право читать запись A, но не имеет права читать запись B. Если после замены идентификатора сервер возвращает запись B, нарушается конфиденциальность данных.

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

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

Тестировщик создаёт как минимум два объекта, принадлежащих разным пользователям или ролям. Затем он выполняет один и тот же запрос от имени пользователя A, последовательно подставляя идентификатор собственного объекта и объекта пользователя B.

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

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

Нужно различать аутентификацию и авторизацию. Аутентификация отвечает на вопрос, кто пользователь, а авторизация — что именно этому пользователю разрешено делать. Пользователь может быть корректно аутентифицирован, но всё равно не иметь права читать конкретную запись.

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

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

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

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

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

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

  1. Дополнительный вопрос: Достаточно ли заменить идентификатор на случайный UUID, чтобы устранить проблему?

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

  1. Дополнительный вопрос: Почему ответ «ресурс не найден» иногда предпочтительнее ответа «доступ запрещён»?

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

  1. Дополнительный вопрос: Нужно ли отдельно проверять пакетный запрос, если одиночный доступ уже защищён?

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