flawopen.com/Обход пути/Zip Slip
Что такое уязвимость Zip Slip?
В ZIP-архиве может быть имя ../../outside.txt. Если распаковщик ему доверяет, файл запишется за пределами целевого каталога — в пределах прав процесса.
Почему это легко пропустить
Распаковка кажется обычной операцией, но создатель недоверенного ZIP- или TAR-архива задаёт имена его записей. Соединение outputDir + entry.name без проверки пути позволяет выйти из каталога через содержимое архива.
for entry in zip_file:
dest = os.path.join(output_dir, entry.name)
write_file(dest, entry.read())
# entry.name может быть "../../outside.txt"
root = os.path.realpath(output_dir)
os.makedirs(root, exist_ok=True)
for entry in zip_file:
dest = os.path.realpath(
os.path.join(root, entry.name)
)
try:
inside_root = os.path.commonpath([root, dest]) == root
except ValueError:
inside_root = False
if not inside_root:
raise ValueError("Unsafe entry path")
write_file(dest, entry.read())
Эта проверка блокирует выходы за каталог, в том числе соседние пути с одинаковым текстовым префиксом. Распаковывайте в новую закрытую директорию, отклоняйте записи-symlink и учитывайте существующие symlink и параллельные изменения файловой системы — для этого нужны API, устойчивые к гонкам, или поддерживаемая библиотека распаковки.
Частые вопросы
В Python API архивов по-разному защищают пути
Показанная выше пара кода — концептуальный пример собственного цикла распаковки, а не встроенный метод Python ZipFile.extractall(). В документации Python сказано, что ZipFile.extract() и extractall() пытаются предотвращать выход за каталог через абсолютные пути и .., но также рекомендуется проверять недоверенные архивы. zipfile.Path не очищает имена элементов, поэтому вызывающий код должен проверять их сам. Фильтры извлечения TAR появились в Python 3.12; в Python 3.14 значением по умолчанию стал filter="data". В поддерживаемых версиях задавайте этот фильтр явно, если значение по умолчанию может быть менее строгим. Даже фильтр data не блокирует все небезопасные действия и риски исчерпания ресурсов. Распаковывайте архив в новый закрытый временный каталог и ограничивайте размер архива, число элементов, общий объём распакованных данных и время обработки.
В некоторых версиях после широкой огласки этого шаблона в 2018 году появилась защита; другие не проверяют пути по умолчанию. Проверьте документацию своей версии и явно валидируйте каждую запись.