Введение

Класс программных ошибок
В разработке программного обеспечения, состояние между проверкой и использованием (TOCTOU, TOCTTOU или TOC/TOU) — это класс программных ошибок, вызванных гонкой данных, возникающей при проверке состояния части системы (например, учетных данных безопасности) и последующем использовании результата этой проверки. Гонки TOCTOU часто встречаются в Unix при операциях с файловой системой, но могут возникать и в других контекстах, включая локальные сокеты и некорректное использование транзакций базы данных. В начале 1990-х годов почтовая утилита BSD 4.3 UNIX содержала уязвимость, связанную с гонкой данных при работе с временными файлами, из-за использования функции mktemp. Ранние версии OpenSSH также имели уязвимость, связанную с гонкой данных при работе с Unix domain sockets. Данная проблема остаётся актуальной и в современных системах: по состоянию на 2019 год, гонка TOCTOU в Docker позволяла получить права root-пользователя к файловой системе хост-платформы. На конкурсе Pwn2Own 2023 в Ванкувере команда хакеров смогла скомпрометировать шлюз обновлённой Tesla Model 3, используя эту уязвимость.

Надежное время TOCTOU

Использование уязвимости TOCTOU требует точной синхронизации, чтобы операции атакующего и жертвы выполнялись в нужном порядке. В приведенном выше примере атакующий должен выполнить системный вызов создания символической ссылки точно между проверкой доступа и открытием файла. Для наиболее общей атаки атакующий должен быть запланирован для выполнения после каждой операции жертвы, что также известно как "пошаговое" выполнение жертвы. Это применимо к почтовой утилите BSD 4.3 и mktemp, а также к атакам, основанным на алгоритмической сложности. В обоих случаях атакующий манипулирует состоянием операционной системы, чтобы контролировать планирование жертвы. "Файловые лабиринты" вынуждают жертву читать запись каталога, отсутствующую в кэше ОС, и ОС переводит жертву в состояние ожидания, пока она считывает каталог с диска. Атаки, основанные на алгоритмической сложности, вынуждают жертву тратить весь квант времени на выполнение внутри одного системного вызова, обходя хэш-таблицу ядра с кэшем имен файлов. Атакующий создает большое количество файлов с именами, которые хешируются в то же значение, что и файл, который будет искать жертва.

Как предотвратить ОБЯЗАНИЕ

Несмотря на концептуальную простоту, условия гонки TOCTOU трудно избежать и устранить. Один из общих методов – использование обработки ошибок вместо предварительной проверки, в соответствии с философией EAFP – "легче попросить прощения, чем разрешения", а не LBYL – "смотри, прежде чем прыгать". В этом случае проверка отсутствует, а нарушение предположений сигнализируется возвратом ошибки. В контексте условий гонки TOCTOU в файловой системе, основная задача заключается в обеспечении невозможности изменения файловой системы между двумя системными вызовами. В 2004 году был опубликован результат, доказывающий невозможность существования переносимого, детерминированного метода предотвращения условий гонки TOCTOU при использовании системных вызовов UNIX access и open для файловой системы. После публикации этого результата, исследователи предложили библиотеки для отслеживания дескрипторов файлов и обеспечения корректности. Альтернативным решением, предложенным в научном сообществе, является внедрение транзакций в файловую систему или ядро ОС UNIX. Транзакции предоставляют абстракцию управления параллелизмом для ОС и могут быть использованы для предотвращения гонок TOCTOU. Хотя ни одно производственное ядро UNIX пока не внедрило транзакции, для Linux были разработаны исследовательские прототипы, включая файловую систему Valor и ядро TxOS. Microsoft Windows добавила транзакции в свою файловую систему NTFS, но Microsoft не рекомендует их использовать и заявила о возможности их удаления в будущей версии Windows. Блокировка файлов – распространенный метод предотвращения условий гонки для отдельного файла, однако он не распространяется на пространство имен файловой системы и другие метаданные, плохо работает с сетевыми файловыми системами и не может предотвратить условия гонки TOCTOU. Для setuid-бинарников возможным решением является использование системного вызова seteuid для изменения эффективного пользователя, а затем выполнения операции открытия файла. Различия в реализации setuid между операционными системами могут быть проблематичными.