В разработке программного обеспечения время проверки времени использования ( TOCTOU , TOCTTOU или TOC/TOU ) — это класс программных ошибок , вызванных состоянием гонки , включающим проверку состояния части системы (например, учетные данные безопасности) и использование результатов этой проверки.
Условия гонки TOCTOU распространены в Unix между операциями в файловой системе [1] , но могут возникать и в других контекстах, включая локальные сокеты и неправильное использование транзакций базы данных . В начале 1990-х годов почтовая утилита BSD 4.3 UNIX имела возможность использования состояния гонки для временных файлов, поскольку она использовала функцию mktemp()
[2] . [3]
Ранние версии OpenSSH имели возможность использования состояния гонки для сокетов домена Unix . [4] Они остаются проблемой в современных системах; с 2019 года состояние гонки TOCTOU в Docker обеспечивает root-доступ к файловой системе хост-платформы. [5] На соревновании Pwn²Own 2023 года в Ванкувере команда хакеров смогла взломать шлюз в обновленной модели Tesla 3, используя эту ошибку. [6]
В Unix следующий код C при использовании в setuid
программе содержит ошибку TOCTOU:
if ( access ( "файл" , 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: дата и год ( ссылка )