
Documenta CVE-2026-65320, un path traversal di tipo tar-slip in untar_dir() di fastcore, con un proof-of-concept innocuo che dimostra la scrittura arbitraria di file e l'esecuzione di codice.
untar_dir()Gravità: Critica, CVSS 3.1 9.8
Vettore (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Interessato: fastcore <= 2.2.30
Corretto in: Non corretto al momento della stesura
CWE: CWE-22 (Limitazione impropria di un percorso a una directory ristretta, 'Path Traversal')
Componente: fastcore.xtras.untar_dir() → fastcore.xtras._unpack() → shutil.unpack_archive()
Runtime ad alto rischio: Python < 3.14 (Python 3.14 rende predefinito il filtro tar sicuro data)
Segnalato da: Rahul Karne
CNA: VulnCheck
fastcore.xtras.untar_dir(fname, dest) è un helper documentato che estrae un archivio "in dest".
Internamente, passa l'archivio alla funzione della libreria standard shutil.unpack_archive() senza un filtro di estrazione, senza validare i percorsi dei membri dell'archivio e senza alcun controllo di contenimento post-estrazione.
Di conseguenza, un archivio TAR i cui membri contengono sequenze di traversal ../ o percorsi assoluti può scrivere file al di fuori della directory in cui il chiamante ha chiesto a fastcore di estrarre.
Un chiamante che si aspetta ragionevolmente che untar_dir(fname, dest) confini tutto in dest ottiene invece una scrittura arbitraria di file ovunque il processo possa scrivere.
Scrittura arbitraria di file sotto l'autorità del processo che chiama untar_dir().
A seconda di ciò che viene sovrascritto, questo può comportare:
La proof of concept dimostra l'intera catena scrittura → import → esecuzione di codice dall'inizio alla fine, interamente all'interno di una directory demo innocua.
fastcore è una dipendenza fondamentale in tutto l'ecosistema fast.ai, tra cui:
fastainbdevghapiRiceve decine di milioni di download al mese.
untar_dir() è la primitiva di estrazione alla base del comune flusso di lavoro "scarica un archivio, poi estrailo", che segue lo stesso schema generale di untar_data di fastai.
Qualsiasi percorso di codice che alimenta untar_dir() con un archivio i cui contenuti non sono completamente attendibili è esposto.
Il codice vulnerabile esiste in fastcore/xtras.py:
def _unpack(fname, out):
import shutil
shutil.unpack_archive(str(fname), str(out)) # <-- no filter, no validation
ls = out.ls()
return ls[0] if len(ls) == 1 else out
def untar_dir(fname, dest, rename=False, overwrite=False, uid=-1, gid=-1):
"untar `file` into `dest` ..."
import tempfile, shutil
dest = Path(dest)
with tempfile.TemporaryDirectory() as d:
out = Path(d) / remove_suffix(Path(fname).stem, '.tar')
out.mkdir()
...
src = _unpack(fname, out) # extraction escapes `out` here
...
shutil.move(str(src), dest)
...
return dest
untar_dir() crea una directory temporanea interna di estrazione:
<tempdir>/<random>/<archive-stem>/
Poi chiama _unpack(), che inoltra l'archivio direttamente a:
shutil.unpack_archive()
Per gli archivi TAR, questo alla fine chiama tarfile.extractall().
Su Python < 3.14, il comportamento di estrazione predefinito è fully_trusted, il che significa che i membri con traversal possono essere onorati.
Ad esempio, un membro dell'archivio come:
../../../some/other/dir/file
viene scritto relativamente alla directory di estrazione e può quindi uscirne.
Nulla in fastcore:
filter="data" dove supportato....untar_dir() tratta shutil.unpack_archive() come se fosse un estrattore di archivi sicuro e sandboxed.
Non lo è.
La documentazione della libreria standard di Python avverte che estrarre archivi non attendibili può creare file al di fuori della destinazione richiesta e raccomanda un filtraggio di estrazione sicuro per gli archivi TAR.
fastcore né passa un filtro di estrazione appropriato né implementa una protezione di contenimento equivalente per le versioni di Python che supporta.
Inoltre non avverte i chiamanti di untar_dir() di questo comportamento sensibile alla sicurezza.
I membri TAR possono contenere stringhe di percorso arbitrarie.
Sulle versioni di Python interessate, tarfile.extractall() non neutralizza automaticamente le sequenze di traversal .. per impostazione predefinita.
Scrivere un membro con traversal relativamente alla directory temporanea di estrazione di fastcore è quindi sufficiente per uscire da quella directory e scrivere ovunque il processo abbia il permesso di scrivere.
Una primitiva affidabile è il traversal relativo come:
../../../target/file
Questa è la tecnica utilizzata dalla proof of concept.
L'input pericoloso è il contenuto dell'archivio, non il percorso di destinazione scelto dallo sviluppatore.
Gli archivi sono spesso ottenuti da posizioni esterne o semi-attendibili, tra cui:
Qualsiasi servizio o strumento che scarica un archivio da una fonte non attendibile o semi-attendibile e successivamente lo elabora usando untar_dir() può quindi essere raggiungibile.
La PoC include anche una variante che serve l'archivio creato ad hoc da un endpoint HTTP controllato dall'attaccante per dimostrare questo percorso di consegna.
Lo sfruttamento riuscito richiede:
L'applicazione chiama fastcore.xtras.untar_dir() su un archivio i cui contenuti sono influenzati dall'attaccante, come un archivio caricato, scaricato o altrimenti non attendibile.
Il runtime utilizza Python < 3.14, o un'altra configurazione in cui un filtro di estrazione TAR sicuro non è applicato.
Per l'escalation da scrittura arbitraria di file a esecuzione di codice, il processo successivamente importa o carica un file da una posizione raggiungibile dal traversal, come:
La scrittura arbitraria di file e la modifica di configurazione/dati richiedono solo le condizioni 1 e 2.
poc_fastcore_cna_demo.py invoca l'API reale fastcore.xtras.untar_dir().
La dimostrazione è intenzionalmente innocua.
Ogni file creato dalla PoC rimane all'interno di una singola directory demo specificata usando:
--demo-root
La PoC non modifica file di sistema reali e non accede a servizi cloud o credenziali.
Stampa i dettagli dell'ambiente e il codice sorgente vulnerabile per _unpack() e untar_dir().
Crea un layout dimostrativo contenente:
service_app/plugins/
Crea:
attacker_supplied_upload.tar
contenente membri dell'archivio progettati per puntare al di fuori della radice di estrazione prevista, inclusi membri con traversal e:
service_app/plugins/startup_hook.py
def auto_extract_uploaded_archive(received_archive):
return untar_dir(
received_archive,
intended_root,
overwrite=True
)
Verifica che i file siano stati scritti al di fuori della directory di estrazione prevista.
Simula un ricaricamento del servizio importando il file scritto dall'archivio:
startup_hook.py
L'hook di avvio innocuo crea:
SERVICE_RELOAD_MARKER
Questo dimostra la catena completa:
Attacker-controlled archive
↓
Path traversal during extraction
↓
Arbitrary file write
↓
Write into importable / auto-loaded location
↓
Application loads attacker-controlled file
↓
Code execution
Installa il pacchetto interessato:
pip install fastcore
Il problema è stato confermato tramite:
fastcore 2.2.30
La dimostrazione può essere eseguita su:
fastcore installata con pip--sourceTutte le scritture della PoC rimangono all'interno della directory specificata tramite --demo-root.
Pulisci qualsiasi output precedente della PoC:
python poc_fastcore_cna_demo.py --demo-root ./poc_fastcore --clean
Esegui la dimostrazione:
python poc_fastcore_cna_demo.py \
--demo-root ./poc_fastcore \
--source latest \
--no-pause
Esempio di output abbreviato:
fastcore version: 2.2.30
Outside marker exists after extraction? True
Is outside marker inside intended extraction root? False
Relative traversal marker exists after extraction? True
Is relative traversal marker inside intended extraction root? False
Service plugin file exists after extraction? True
Service reload marker exists? True
POC WORKED: fastcore extracted attacker-controlled tar members outside the intended root.
Sulle versioni di Python supportate, usa un filtro di estrazione sicuro come:
filter="data"
con shutil.unpack_archive() o la corrispondente operazione di estrazione tarfile.
Ogni membro dell'archivio dovrebbe essere controllato prima dell'estrazione.
Rifiuta:
..Anche le destinazioni dei link dovrebbero essere risolte e validate prima dell'estrazione.
Risolvi ogni percorso di destinazione prima di scrivere e verifica che rimanga sotto la radice di estrazione prevista.
Concettualmente:
resolved_member_path
↓
must remain inside
↓
resolved_extraction_root
L'estrazione dovrebbe fallire se la destinazione risolta esce dalla radice di estrazione.
I test di regressione dovrebbero coprire almeno:
../ traversal
absolute paths
Windows drive-letter paths
UNC paths
symbolic links
hard links
Documenta chiaramente se untar_dir() è destinato a elaborare in modo sicuro archivi non attendibili.
Se l'estrazione non sicura è intenzionalmente supportata, il comportamento sicuro dovrebbe comunque essere quello predefinito.
Il comportamento non sicuro dovrebbe richiedere un opt-in esplicito invece di fidarsi silenziosamente dei contenuti dell'archivio.
Fino al rilascio di una correzione a livello di pacchetto:
untar_dir().Il difetto tecnico sottostante è una vulnerabilità di scrittura arbitraria di file causata dal path traversal dell'archivio.
Tuttavia, la gravità finale dipende dall'ambiente di distribuzione e da come untar_dir() è esposto.
Un vettore rappresentativo può avvicinarsi a:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Risultato:
9.8 — Critica
Se lo sfruttamento richiede invece che uno sviluppatore scarichi ed estragga manualmente un archivio, l'interazione utente e la complessità dell'attacco possono essere maggiori.
Il punteggio CVSS risultante sarebbe quindi materialmente inferiore.
Due fattori importanti dovrebbero essere considerati quando si valuta il problema.
Questa è un'istanza della classe di vulnerabilità di estrazione TAR non sicura nota da tempo associata a:
CVE-2007-4559
Le versioni moderne di Python hanno introdotto un comportamento di estrazione di archivi più sicuro.
Python 3.14 rende predefinito il filtro di estrazione sicuro data.
Pertanto, l'ambiente principalmente interessato è Python < 3.14.
Tuttavia, quei runtime rimangono ampiamente distribuiti.
La vulnerabilità diventa sfruttabile quando un chiamante fornisce a untar_dir() un archivio i cui contenuti sono controllati dall'attaccante o altrimenti non attendibili.
Questo report tratta quindi i contenuti dell'archivio come il confine di sicurezza non attendibile.
Un helper robusto per l'estrazione di archivi dovrebbe fallire in modo sicuro indipendentemente da come è stato ottenuto l'archivio.
Sostituisci le date segnaposto di seguito con le date effettive di divulgazione.
YYYY-MM-DD — Vulnerabilità segnalata ai manutentori.YYYY-MM-DD — Risposta del fornitore / conferma / nessuna risposta.2.2.30); il codice di estrazione è rimasto invariato.Scoperto e segnalato da Rahul Karne.
Documentazione di fastcore untar_dir()
https://fastcore.fast.ai/xtras.html
Sorgente di fastcore xtras.py
https://github.com/AnswerDotAI/fastcore/blob/main/fastcore/xtras.py
fastcore su PyPI
https://pypi.org/project/fastcore/
Documentazione di Python shutil.unpack_archive()
https://docs.python.org/3/library/shutil.html#shutil.unpack_archive
Filtri di estrazione di Python tarfile
https://docs.python.org/3/library/tarfile.html#extraction-filters
PEP 706 — Filter for tarfile.extractall
https://peps.python.org/pep-0706/
CWE-22 — Improper Limitation of a Pathname to a Restricted Directory
https://cwe.mitre.org/data/definitions/22.html
CVE-2007-4559 — Classe di vulnerabilità di estrazione TAR non sicura
https://nvd.nist.gov/vuln/detail/CVE-2007-4559
Questo repository documenta un risultato di sicurezza a divulgazione coordinata e fornisce una proof of concept innocua e autonoma.
La PoC scrive solo all'interno della directory --demo-root specificata dall'utente e non esegue azioni distruttive.
Qualsiasi funzionalità di rete inclusa nella dimostrazione è limitata a una dimostrazione locale opzionale.
Questo materiale è fornito per ricerca di sicurezza difensiva e scopi educativi.
Richieste dei media: [email protected]. PoC completa (server attaccante, archivio con traversal, applicazione vittima) e ulteriori dettagli tecnici disponibili su richiesta.