Время проверки — время использования
Время проверки — время использования (англ. time-of-check to time-of-use, TOCTOU, TOCTTOU или TOC/TOU) — класс программных ошибок, связанных с условием гонки, возникающим в промежутке между проверкой состояния части системы (например, проверки полномочий безопасности) и использованием результата этой проверки[1].
Ошибки времени проверки — времени использования особенно распространены в операционных системах семейства Unix при операциях с файловой системой[1], но могут возникать и в других контекстах, включая локальные сокеты и неправильное использование транзакций в базах данных. В начале 1990-х годов в утилите электронной почты BSD 4.3 UNIX существовало эксплуатируемое условие гонки, связанное с временными файлами, поскольку использовалась функция mktemp()[2][3]. В ранних версиях OpenSSH также существовало эксплуатируемое условие гонки при работе с сокетами Unix[4]. Данная проблема продолжает встречаться в современных системах: по состоянию на 2019 год уязвимость типа TOCTOU в Docker позволяла получить root-доступ к файловой системе хоста[5]. В 2023 году на соревновании Pwn2Own в Ванкувере команда хакеров с помощью подобной уязвимости скомпрометировала шлюз в обновлённой версии Tesla Model 3[6].
Примеры
В Unix следующий код на языке C, используемый в программе с setuid, содержит ошибку TOCTOU:
if (access("file", W_OK) != 0) {
exit(1);
}
fd = open("file", O_WRONLY);
write(fd, buffer, sizeof(buffer));
Здесь функция access проверяет, имеет ли реальный пользователь, запустивший программу с setuid, право на запись в файл (то есть access проверяет реальный идентификатор пользователя, а не эффективный идентификатор пользователя).
Подобное условие гонки может быть использовано для атаки:
| Жертва | Злоумышленник |
|---|---|
if (access("file", W_OK) != 0) {
exit(1);
}
|
|
После проверки доступа, до открытия файла, злоумышленник заменяет file на символьную ссылку (symlink) на файл паролей Unix /etc/passwd:
symlink("/etc/passwd", "file");
| |
fd = open("file", O_WRONLY);
write(fd, buffer, sizeof(buffer));
Фактически происходит запись поверх |
В этом примере злоумышленник может использовать условие гонки между access и open, чтобы вынудить жертву с setuid перезаписать запись в системной базе паролей. Ошибки типа TOCTOU могут использоваться для повышения привилегий и получения административного доступа к системе.
Хотя подобная последовательность требует точного согласования во времени, злоумышленник может добиться подходящих условий относительно несложно.
Такие уязвимости показывают, что приложение не может полагаться на то, что состояние, управляемое операционной системой (в данном случае пространство имён файловой системы) не изменится между системными вызовами.
Надёжное воспроизведение TOCTOU
Эксплуатация уязвимости типа TOCTOU требует точного согласования во времени, чтобы операции злоумышленника выполнялись между операциями жертвы. В приведённом выше примере злоумышленнику необходимо выполнить системный вызов symlink строго между access и open. Для наиболее общего случая атаки планировщик должен «подпускать» злоумышленника после каждой операции жертвы, что называется «однократной пошаговой» работой жертвы.
В случае с утилитой mail из BSD 4.3 и mktemp()[2], достаточно запускать утилиту почты в одном процессе, а в другом — угадывать имена временных файлов и создавать символьные ссылки. Такая атака обычно срабатывает в течение одной минуты.
Техники пошагового воздействия на жертву включают создание «лабиринтов» в файловой системе[7] и атаки на алгоритмическую сложность[8]. Везде злоумышленник приводит ОС в особое состояние, чтобы контролировать расписание жертвы.
«Лабиринты» в файловой системе вынуждают жертву читать элемент каталога вне кэша ОС, и ОС «усыпляет» жертву на время чтения каталога с диска. Атакой по алгоритмической сложности заставляют жертву весь выделенный ей квант процессорного времени проводить в одном системном вызове, обходя хеш-таблицу кэша имён файлов. Для этого злоумышленник создаёт множество файлов, имена которых хешируются так же, как файл, который будет искать жертва.
Предотвращение TOCTOU
Несмотря на концептуальную простоту, ошибки времени проверки — времени использования очень сложно предотвратить и полностью устранить. Одним из общих подходов является обработка ошибок вместо «предварительной проверки», согласно принципу EAFP («лучше потом извиниться, чем попросить разрешения») вместо LBYL («сначала посмотри, потом прыгай»). В таком подходе не проводится предварительная проверка, и сбой предположения фиксируется по возвращаемой ошибке[9].
В контексте TOCTOU из-за файловой системы основная проблема — обеспечение того, чтобы состояние файловой системы не изменилось между двумя системными вызовами. В 2004 году была опубликована работа, показывающая невозможность — отсутствие портативной и детерминированной техники, полностью исключающей TOCTOU при использовании стандартных вызовов Unix access и open[10].
Впоследствии были предложены исследовательские библиотеки для отслеживания файловых дескрипторов и контроля корректности[11].
В качестве альтернативного решения в научном сообществе предлагается реализовать транзакции на уровне файловой системы или ядра ОС. Транзакции предоставляют механизм контроля параллелизма для ОС и могут предотвратить TOCTOU. Хотя ни одно производственное ядро Unix пока не реализовало транзакции, экспериментальные прототипы были созданы для Linux, например файловая система Valor[12] и ядро TxOS[13]. В операционной системе Microsoft Windows транзакции добавлены в файловую систему NTFS[14], однако их использование не рекомендуется компанией Microsoft, и возможно, что эта возможность будет удалена в будущих версиях Windows[15].
Блокировка файлов часто применяется для предотвращения условий гонки с отдельным файлом, но не защищает пространство имён файловой системы или другую метаинформацию. Блокировка плохо масштабируется для сетевых файловых систем и не может предотвратить TOCTOU.
Для бинарных файлов с setuid потенциальным решением может быть использование системного вызова seteuid() для изменения эффективного пользователя перед вызовом open(). Однако различия в реализации setuid() между ОС могут создать дополнительные сложности[16].
Примечания
- ↑ 1 2 Wei, Jinpeng; Pu, Calton TOCTTOU Vulnerabilities in UNIX-Style File Systems: An Anatomical Study. USENIX (декабрь 2005). Дата обращения: 14 января 2019.
- ↑ 1 2 mktemp(3). Linux manual page (15 сентября 2017).
- ↑ Shangde Zhou (周尚德). A Security Loophole in Unix (англ.) (1 октября 1991). Архивировано 16 января 2013 года.
- ↑ Acheson, Steve The Secure Shell (SSH) Frequently Asked Questions (4 ноября 1999). Архивировано 13 февраля 2017 года.
- ↑ Docker Bug Allows Root Access to Host File System. Decipher. Duo Security (28 мая 2019). Дата обращения: 29 мая 2019.
- ↑ Windows 11, Tesla, Ubuntu, и macOS взломаны на Pwn2Own 2023 (англ.). BleepingComputer. Дата обращения: 24 марта 2023.
- ↑ Borisov, Nikita; Johnson, Rob; Sastry, Naveen; Wagner, David (август 2005). “Fixing races for fun and profit: how to abuse atime”. Proceedings of the 14th Conference on USENIX Security Symposium. Baltimore, MD: USENIX Association. 14: 303—314. CiteSeerX 10.1.1.117.7757. Проверьте дату в
|date=(справка на английском) - ↑ Xiang Cai. Exploiting Unix File-System Races via Algorithmic Complexity Attacks // 2009 30th IEEE Symposium on Security and Privacy / Xiang Cai, Yuwei Gui, Rob Johnson. — Berkeley, CA : IEEE Computer Society, май 2009. — P. 27–41. — ISBN 978-0-7695-3633-0. — doi:10.1109/SP.2009.10.
- ↑ Martelli, Alex. Глава 6: Исключения // Python in a Nutshell. — 2. — O'Reilly Media, 2006. — P. 134. — ISBN 978-0-596-10046-9.
- ↑ Dean, Drew; Hu, Alan J. (август 2004). “Fixing Races for Fun and Profit: How to use access(2)”. Proceedings of the 13th USENIX Security Symposium. San Diego, CA: 195—206. CiteSeerX 10.1.1.83.8647. Проверьте дату в
|date=(справка на английском) - ↑ Tsafrir, Dan; Hertz, Tomer; Wagner, David; Da Silva, Dilma Portably Preventing File Race Attacks with User-Mode Path Resolution. Technical Report RC24572, IBM T. J. Watson Research Center (июнь 2008).
- ↑ Spillane, Richard P.; Gaikwad, Sachin; Chinni, Manjunath; Zadok, Erez Enabling Transactional File Access via Lightweight Kernel Extensions. Seventh USENIX Conference on File and Storage Technologies (FAST 2009) (27 февраля 2009).
- ↑ Porter, Donald E.; Hofmann, Owen S.; Rossbach, Christopher J.; Benn, Alexander; Witchel, Emmett Operating System Transactions. Proceedings of the 22nd ACM Symposium on Operating Systems Principles (SOSP '09) (14 октября 2009).
- ↑ Russinovich, Mark. Windows Internals / Mark Russinovich, David A. Solomon. — Microsoft Press. — ISBN 978-0735648739.
- ↑ Alternatives to using Transactional NTFS. Microsoft Developer Network. Дата обращения: 10 декабря 2015. Архивировано 29 сентября 2022 года.
- ↑ Setuid Demystified (12 мая 2002).
Литература
- Bishop, Matt; Dilger, Michael Checking for Race Conditions in File Accesses. Computing Systems 131–152 (1996).
- Tsafrir, Dan; Hertz, Tomer; Wagner, David; Da Silva, Dilma Portably Solving File TOCTTOU Races with Hardness Amplification. Proceedings of the 6th USENIX Conference on File and Storage Technologies (FAST '08), San Jose (CA), February 26–29, 2008 189–206 (2008).