В стандартной библиотеке языка Rust выявлена уязвимость (CVE-2022-21658), связанная с состоянием гонки в функции std::fs::remove_dir_all(). В случае применения данной функции для удаления временных файлов в привилегированном приложении, злоумышленник может добиться удаления произвольных системных файлов и каталогов, к удалению которых в обычных условиях у атакующего нет доступа.
Уязвимость вызвана некорректной реализацией проверки символических ссылок перед рекурсивным удалением каталогов. Вместо запрета следования по символическим ссылкам, функция remove_dir_all() вначале проверяет, является ли файл символической ссылкой. Если определена ссылка, то она удаляется как файл, а если каталог – то вызывается операция рекурсивного удаления содержимого. Проблема в том, что между проверкой и началом операции удаления имеется небольшая задержка.
В момент, когда проверка уже проведена, но операция перебора каталогов для удаления ещё не началась, атакующий может подменить каталог со временными файлами на символическую ссылку. В случае успеха, функция remove_dir_all() обработает символическую ссылку как каталог и начнёт удаление содержимого на которое, указывает данная ссылка. Несмотря не то, что успех атаки зависит от точности выбранного времени замены каталога и попадание с первого раза в нужный момент маловероятно, в ходе экспериментов исследователям добиться повторяемого успешного проведения атаки за несколько секунд.
Уязвимости подвержены все версии Rust с 1.0.0 по 1.58.0 включительно. Проблема пока устранена в форме патча (исправление будет включено в выпуск 1.58.1, который ожидается в течение нескольких часов). Проследить за устранением уязвимости в дистрибутивах можно на данных страницах: Debian, RHEL, SUSE, Fedora, Ubuntu, Arch, FreeBSD. Всем пользователям программ на языке Rust, выполняемым с повышенными привилегиями и использующим функцию remove_dir_all, рекомендуется срочно обновить Rust до версии 1.58.1. Интересно, что выпущенный патч решает проблему не на всех системах, например, в ОС REDOX и версиях macOS до 10.10 (Yosemite), уязвимость не блокируется из-за отсутствия флага O_NOFOLLOW, отключающего следование по символическим ссылкам.