В разработке программного обеспечения ошибки от времени проверки до времени использования ( TOCTOU , TOCTTOU или TOC/TOU ) — это класс ошибок программного обеспечения, вызванных состоянием гонки , включающим проверку состояния части системы (например, учетных данных безопасности) и использование результатов этой проверки.
Условия гонки TOCTOU распространены в Unix между операциями в файловой системе , [1] но могут возникать и в других контекстах, включая локальные сокеты и неправильное использование транзакций базы данных . В начале 1990-х годов почтовая утилита BSD 4.3 UNIX имела эксплуатируемое состояние гонки для временных файлов, поскольку она использовала функцию mktemp()
[2] . [3]
Ранние версии OpenSSH имели эксплуатируемое состояние гонки для доменных сокетов Unix . [4] Они остаются проблемой в современных системах; по состоянию на 2019 год условие гонки TOCTOU в Docker позволяет получить доступ с правами root к файловой системе хост-платформы. [5] На соревновании Pwn2Own 2023 года в Ванкувере команда хакеров смогла скомпрометировать шлюз в обновленной модели Tesla 3, используя эту ошибку. [6]
В Unix следующий код Csetuid
при использовании в программе содержит ошибку TOCTOU:
если ( доступ ( "файл" , W_OK ) != 0 ) { выход ( 1 );}fd = открыть ( "файл" , O_WRONLY ); запись ( fd , буфер , sizeof ( буфер ));
В данном случае доступ предназначен для проверки того, setuid
разрешено ли реальному пользователю, запустившему программу, записывать файл (т. е. access
проверяется реальный идентификатор пользователя , а не эффективный идентификатор пользователя ).
Это состояние гонки уязвимо для атаки:
В этом примере злоумышленник может использовать состояние гонки между access
и , open
чтобы обманом setuid
заставить жертву перезаписать запись в базе данных паролей системы. Гонки TOCTOU могут использоваться для повышения привилегий с целью получения административного доступа к машине.
Хотя эта последовательность событий требует точного расчета времени, злоумышленник может организовать такие условия без особых затруднений.
Подразумевается, что приложения не могут предполагать, что состояние, управляемое операционной системой (в данном случае пространство имен файловой системы), не изменится между системными вызовами.
Эксплуатация состояния гонки TOCTOU требует точного расчета времени, чтобы гарантировать, что операции атакующего правильно чередуются с операциями жертвы. В приведенном выше примере атакующий должен выполнить symlink
системный вызов точно между access
и open
. Для наиболее общей атаки атакующий должен быть запланирован для выполнения после каждой операции жертвы, что также известно как «пошаговое выполнение» жертвы.
В случае с почтовой утилитой BSD 4.3 и mktemp()
[ 2] злоумышленник может просто продолжать запускать почтовую утилиту в одном процессе, и продолжать угадывать имена временных файлов и продолжать создавать символические ссылки в другом процессе. Атака обычно может быть успешной менее чем за одну минуту.
Методы пошагового выполнения программы-жертвы включают в себя лабиринты файловой системы [7] и атаки на алгоритмическую сложность. [8] В обоих случаях злоумышленник манипулирует состоянием ОС, чтобы контролировать планирование жертвы.
Лабиринты файловой системы заставляют жертву читать запись каталога, которой нет в кэше ОС, и ОС усыпляет жертву, пока она читает каталог с диска. Атаки на алгоритмическую сложность заставляют жертву тратить весь свой квант планирования внутри одного системного вызова, проходя по хэш-таблице ядра кэшированных имен файлов. Злоумышленник создает очень большое количество файлов с именами, хэш которых совпадает с файлом, который будет искать жертва.
Несмотря на концептуальную простоту, состояния гонки TOCTOU трудно избежать и устранить. Одним из общих методов является использование обработки ошибок вместо предварительной проверки в соответствии с философией EAFP – «Проще попросить прощения, чем разрешения», а не LBYL – «посмотри, прежде чем прыгнуть» – в этом случае проверка отсутствует, а невыполнение предположений сигнализируется возвращением ошибки. [9]
В контексте условий гонки TOCTOU файловой системы фундаментальной проблемой является обеспечение невозможности изменения файловой системы между двумя системными вызовами. В 2004 году был опубликован результат невозможности, показывающий, что не существует переносимой, детерминированной техники для избежания условий гонки TOCTOU при использовании вызовов UNIX access
и open
файловой системы. [10]
Поскольку эта невозможность стала результатом, исследователи предложили библиотеки для отслеживания файловых дескрипторов и обеспечения корректности. [11]
Альтернативное решение, предложенное в исследовательском сообществе, заключается в том, чтобы системы UNIX принимали транзакции в файловой системе или ядре ОС. Транзакции предоставляют абстракцию управления параллелизмом для ОС и могут использоваться для предотвращения гонок TOCTOU. Хотя ни одно производственное ядро UNIX еще не приняло транзакции, для Linux были разработаны экспериментальные прототипы для проверки концепции, включая файловую систему Valor [12] и ядро TxOS. [13] Microsoft Windows добавила транзакции в свою файловую систему NTFS , [14] но Microsoft не рекомендует их использовать и указала, что они могут быть удалены в будущей версии Windows. [15]
Блокировка файлов — это распространенный метод предотвращения состояний гонки для одного файла, но он не распространяется на пространство имен файловой системы и другие метаданные, а также плохо работает с сетевыми файловыми системами и не может предотвратить состояния гонки TOCTOU.
Для setuid
двоичных файлов возможным решением является использование seteuid()
системного вызова для изменения эффективного пользователя и последующего выполнения open()
вызова. Различия setuid()
между операционными системами могут быть проблематичными. [16]
{{cite journal}}
: CS1 maint: дата и год ( ссылка ){{cite book}}
: CS1 maint: отсутствует местоположение издателя ( ссылка ){{cite journal}}
: CS1 maint: дата и год ( ссылка ){{cite web}}
: CS1 maint: дата и год ( ссылка ){{cite web}}
: CS1 maint: дата и год ( ссылка )