Проверка права и выполнение критической операции происходят раздельно. Как проверить, можно ли использовать это окно для обхода авторизации?
Нужно проверить наличие TOCTOU-уязвимости: право проверяется в один момент, а защищаемый объект используется позже, когда его состояние или права уже изменились. Тест должен подтвердить, может ли конкурентное изменение между проверкой и операцией привести к выполнению действия без актуального разрешения.
Безопасный результат достигается, если проверка и операция логически неразделимы либо сервер повторно подтверждает право непосредственно перед изменением критического состояния.
Проблема Time-of-Check to Time-of-Use возникла из общего класса ошибок, где результат проверки считается неизменным, хотя между проверкой и использованием ресурса проходит время. Особенно заметна она в операционных системах и файловых операциях, но тот же механизм применим к веб-приложениям, API, платежам и управлению ролями.
Исходная проблема — рассинхронизация между решением о допустимости действия и фактическим состоянием объекта. Защита строится не вокруг одной проверки, а вокруг сохранения гарантии, что проверенное состояние остаётся действительным до завершения операции.
Например, сервис сначала проверяет, что пользователь может изменить документ, а затем отдельным шагом сохраняет изменения. Между этими действиями администратор может отозвать роль, владелец — изменить права, а сам объект — перейти в другое состояние.
Если сервер использует устаревший результат проверки, пользователь может выполнить запрещённое действие. Последствия зависят от операции: изменение чужих данных, обход согласования, повторное списание или повышение привилегий.
Обычный последовательный тест может не обнаружить дефект, потому что временное окно между операциями мало. Поэтому требуется управляемая конкурентная проверка и наблюдение за фактическим состоянием авторизации на сервере.
Сначала нужно определить границы операции: момент проверки полномочий, момент чтения объекта, момент изменения прав и момент фиксации результата. Затем создаются два конкурентных сценария: один инициирует защищённое действие, второй в заданный момент отзывает право, меняет владельца или переводит объект в запрещённое состояние.
Проверка считается успешной для выявления уязвимости, если после отзыва права операция завершается с эффектом, который должен быть запрещён, либо сервер возвращает успешный результат, хотя актуальное состояние уже не допускает действие. Важно проверять не только HTTP-ответ, но и состояние базы данных, аудита, очередей и внешних систем.
Надёжные варианты защиты — атомарная серверная операция с проверкой права внутри транзакции, блокировка или подходящая версия объекта, условное обновление по ожидаемому состоянию и повторная авторизация перед необратимым действием. Конкретный способ зависит от хранилища и требований к конкурентности.
Одна только блокировка не является универсальным решением: она может снизить производительность, не охватывать внешнюю систему или создавать взаимные блокировки. Повторная проверка также недостаточна, если между ней и изменением снова остаётся окно; критически важно, чтобы проверка и фиксация результата имели согласованную атомарность.
Следует отдельно учитывать уже принятые фоновые задачи. Если запрос только ставит операцию в очередь, право нужно проверять либо при фактическом выполнении, либо гарантировать, что очередь содержит неизменяемое решение с корректной политикой отзыва.
В системе управления документами пользователь с правом согласования отправляет запрос на утверждение. Сервер проверяет роль, затем формирует задачу для фонового обработчика; за это время администратор может отозвать роль.
Рассматривались три варианта. Проверять роль только при создании задачи было просто, но оставляло устаревшее разрешение. Проверять её только в фоне лучше защищало от отзыва, но позволяло пользователю получить вводящий в заблуждение ответ о принятии операции. Транзакционная фиксация решения вместе с записью аудита давала согласованное состояние, но требовала изменить модель обработки.
Выбрали проверку непосредственно перед выполнением фоновой задачи с записью результата и причины отказа. В итоге отозванная роль не позволяла завершить согласование, а интерфейс мог корректно показать, что ранее принятая задача не выполнена из-за изменения полномочий.
Нет, если между второй проверкой и использованием ресурса остаётся новое окно гонки. Повторная проверка снижает вероятность некоторых ошибок, но не устраняет TOCTOU сама по себе. Нужна атомарная связь между последней проверкой, изменением защищаемого состояния и фиксацией результата.
Нет. Тестировщик должен проверять фактические побочные эффекты: изменения данных, отправленные уведомления, созданные задачи, списания и записи во внешних системах. Ошибка после частичного выполнения может быть не менее опасной, чем успешный ответ, поэтому операция должна быть атомарной либо иметь надёжный механизм компенсации.
При ошибке кэширования сервер использует устаревшее разрешение даже без конкурентного изменения в текущем запросе. При TOCTOU критичным является именно изменение между проверкой и использованием. Для различения нужно контролируемо синхронизировать отзыв права с фазами операции и сравнить результаты при последовательном, конкурентном и отключённом кэшировании.