
Dimostra una vulnerabilità di path traversal in uno script di esempio ufficiale di eml-parser, consentendo la scrittura arbitraria di file tramite nomi di allegati appositamente modificati, con PoC e fix.
Lo script di esempio ufficiale examples/recursively_extract_attachments.py contiene una vulnerabilità di path traversal che consente la scrittura arbitraria di file al di fuori della directory di output prevista. I nomi dei file allegati estratti dalle email analizzate vengono utilizzati direttamente per costruire i percorsi dei file di output senza alcuna sanificazione, consentendo a un nome file controllato dall'attaccante di fuoriuscire dalla directory di destinazione.
File: examples/recursively_extract_attachments.py
Righe: 61–64
for a in m['attachment']:
out_filepath = out_path / a['filename'] # No sanitization
print(f'\tWriting attachment: {out_filepath}')
with out_filepath.open('wb') as a_out:
a_out.write(base64.b64decode(a['raw']))
Il valore a['filename'] è controllato dall'attaccante tramite intestazioni di allegati email appositamente create:
Content-Disposition: attachment; filename="../outside/pwned.txt"
Non viene eseguita alcuna normalizzazione del percorso o validazione dei confini prima della scrittura.
.eml dannoso:Content-Disposition: attachment; filename="../outside/pwned.txt"
python recursively_extract_attachments.py -p ./emails -o ./safe
./safe/pwned.txt./outside/pwned.txt ← scritto al di fuori della directory previstaVerificato su Kali Linux con eml-parser installato tramite pip in un ambiente virtuale.
Questa vulnerabilità è limitata solo allo script di esempio e non interessa la libreria principale eml-parser. Tuttavia, poiché lo script fa parte del repository ufficiale ed è probabile che venga adattato per l'uso in produzione, un attaccante che fornisce un'email appositamente creata potrebbe ottenere la scrittura arbitraria di file nel contesto di esecuzione.
Gli scenari di attacco potenziali includono:
filename="../../etc/cron.d/backdoor"filename="../../var/www/html/shell.php"filename="../../home/user/.ssh/authorized_keys"import os.path
for a in m['attachment']:
filename = os.path.basename(a['filename'])
out_filepath = out_path / filename
if not out_filepath.resolve().is_relative_to(out_path.resolve()):
print(f'[!] Skipping suspicious filename: {a["filename"]}')
continue
print(f'\tWriting attachment: {out_filepath}')
with out_filepath.open('wb') as a_out:
a_out.write(base64.b64decode(a['raw']))