Se usi applicazioni web Python su Windows basate su Werkzeug (direttamente o tramite framework come Flask), potresti essere esposto a una vulnerabilità che permette di leggere file non autorizzati sul server.
La buona notizia è che puoi ridurre il rischio in pochi passi:
– Aggiorna Werkzeug all’ultima versione compatibile, soprattutto se sei su Windows.
– Evita di fidarti di percorsi forniti dagli utenti senza una forte validazione.
– Limita l’accesso ai file solo a una cartella sicura e dedicata.
In questa guida trovi prima una spiegazione semplice, pensata per chi non è tecnico, e alla fine una sezione “Technical Deep Dive” con tutti i dettagli per sviluppatori e sistemisti.
—
Introduzione non tecnica: cosa sta succedendo e perché ti riguarda
Werkzeug è una libreria Python molto usata per costruire applicazioni web. Se utilizzi framework come Flask, quasi sicuramente stai usando Werkzeug dietro le quinte.
Su sistemi Windows, alcune versioni di Werkzeug hanno mostrato problemi nella funzione che dovrebbe proteggere i percorsi dei file (la funzione safe_join). In pratica, questa funzione è stata progettata per assicurarsi che l’applicazione non legga o scriva file fuori da una cartella considerata “sicura”.
Purtroppo, in alcuni casi questa protezione non è sufficiente e un attaccante può:
– costruire un percorso “furbo”;
– sfruttare il modo particolare in cui Windows gestisce alcuni nomi speciali e percorsi di rete;
– riuscire così ad accedere a file o dispositivi che non dovrebbero essere visibili dall’applicazione.
Per te questo significa che, se la tua applicazione permette agli utenti di caricare, scaricare o visualizzare file partendo da un nome o un percorso fornito dall’esterno, un attaccante potrebbe provare a leggere dati sensibili.
—
La soluzione rapida per chi gestisce il sistema
Se non sei uno sviluppatore ma gestisci server o applicazioni, concentrati su questi passi:
- Verifica se usi Werkzeug
– Se usi Flask o altri framework Python moderni, è molto probabile che Werkzeug sia presente.
– Controlla il file requirements.txt o il comando pip list per cercare Werkzeug.
- Aggiorna a una versione sicura
– Aggiorna all’ultima versione stabile disponibile di Werkzeug.
– Se possibile, aggiorna anche Python a una versione moderna (almeno 3.11) sui server Windows per beneficiare di controlli più robusti sui percorsi.
- Limita l’accesso ai file
– Assicurati che l’applicazione possa accedere solo a una directory dedicata (ad esempio C:\app\media) e non a tutto il disco.
– Riduci la quantità di file sensibili presenti sullo stesso server dell’applicazione.
- Chiedi una revisione al team di sviluppo
– Domanda esplicitamente: “L’applicazione usa percorsi forniti dagli utenti per leggere o scaricare file? È stata verificata la protezione da path traversal su Windows?”
Se applichi subito questi punti, riduci sensibilmente il rischio di sfruttamento di questa vulnerabilità.
—
Cos’è il path traversal (spiegato semplice)
Il path traversal è un tipo di attacco in cui qualcuno prova a
“scalare” fuori dalla cartella prevista per accedere a file più in alto
nell’albero delle directory.
Immagina di avere una cartella sicura:
– C:\sito\file_utente
L’applicazione dovrebbe aprire solo file dentro questa cartella. Un attaccante, però, potrebbe provare a usare percorsi del tipo:
– ..\..\Windows\system.ini
Se i controlli non sono fatti bene, l’applicazione potrebbe finire per leggere file fuori dalla cartella sicura, ad esempio in C:\Windows. Questo è il cuore del problema: un controllo incompleto sui percorsi permette di uscire dai limiti stabiliti.
—
Perché Windows è un caso particolare
Windows gestisce in modo speciale:
– i percorsi di rete, ad esempio \\server\share;
– i nomi di dispositivo come CON, AUX, NUL, PRN e altri;
– varianti di questi nomi con estensioni (CON.txt) o con spazi finali (CON ).
Questi nomi esistono “virtualmente” in ogni directory. Questo significa che anche se pensi di lavorare in una cartella sicura, un riferimento a un nome speciale può far sì che il sistema operi su qualcosa di diverso da un normale file su disco.
Alcune versioni di Werkzeug non gestiscono correttamente queste particolarità e lasciano passare percorsi che dovrebbero essere bloccati. In combinazione con il comportamento di alcune versioni di Python su Windows, questo rende più facile agli attaccanti costruire percorsi pericolosi.
—
Rischi concreti per una web app Python su Windows
Se la tua applicazione:
– permette di scaricare file passando il nome del file in un parametro (/download?file=...), oppure
– permette di visualizzare immagini o documenti in base a un percorso indicato dall’utente,
allora un uso improprio di safe_join insieme a un controllo insufficiente potrebbe consentire a un attaccante di:
– leggere file che contengono log sensibili, configurazioni o chiavi;
– accedere a dispositivi speciali Windows, con potenziali implicazioni di sicurezza o stabilità;
– sfruttare la vulnerabilità anche da remoto, se l’applicazione è pubblicamente esposta.
Anche se non sono note ondate di attacchi di massa, è comune che vulnerabilità di questo tipo vengano inglobate in strumenti automatizzati di scansione e sfruttamento. Più a lungo resta aperta, maggiore è il rischio.
—
Buone pratiche generali per chi usa Werkzeug su Windows
Ecco alcune buone pratiche immediatamente applicabili anche senza entrare nei dettagli tecnici:
– Aggiornare regolarmente le dipendenze: non solo Werkzeug, ma tutta la catena (framework, librerie di sicurezza, runtime).
– Non fidarsi mai del percorso fornito dall’utente: trattalo sempre come potenzialmente malevolo.
– Usare una directory dedicata ai file degli utenti: non mescolare file di sistema, configurazioni e file caricati o serviti agli utenti.
– Separare ruoli e privilegi: l’account con cui gira l’applicazione dovrebbe avere accesso solo al minimo indispensabile sul file system.
Seguendo queste regole, non solo mitighi questa vulnerabilità specifica, ma innalzi il livello di sicurezza complessivo dell’applicazione.
—
Technical Deep Dive
Questa sezione è pensata per sviluppatori, pentester e sistemisti che desiderano dettagli tecnici su come funziona la vulnerabilità e su come mitigarla in modo robusto.
1. Contesto: ruolo di safe_join in Werkzeug
safe_join è una utility di Werkzeug pensata per:
– ricevere un percorso base (ad esempio la directory radice dei file statici o degli upload);
– ricevere uno o più segmenti di percorso non fidati (tipicamente forniti dall’utente);
– restituire un percorso “unito” che resti confinato sotto la directory base, oppure None/errore se il percorso risultante esce dai limiti.
Lo scopo è mitigare gli attacchi di directory traversal / path traversal senza costringere ogni sviluppatore a reinventare la logica di validazione.
2. Classe di problemi: path traversal e Windows device names
La vulnerabilità si inserisce nella più ampia categoria dei problemi CWE-22 (Improper Limitation of a Pathname to a Restricted Directory) e nella gestione non corretta dei nomi speciali Windows (device names).
Su Windows, esistono device names riservati, come:
– CON
– PRN
– AUX
– NUL
– COM1, COM2, …
– LPT1, LPT2, …
Questi nomi:
– sono accessibili da praticamente qualsiasi directory;
– possono essere usati con estensioni arbitrarie, ad esempio CON.txt;
– possono includere spazi finali, ad esempio CON , che Windows gestisce in modo particolare.
Se una funzione come safe_join controlla solo che il percorso risultante appartenga a una certa directory, ma non valida esplicitamente la presenza di questi nomi speciali, un attaccante può riuscire a far passare un percorso apparentemente innocuo che in realtà punta a un device.
3. Interazione con Python e os.path
Su Windows, alcune versioni di Python presentano peculiarità nella gestione dei percorsi, ad esempio tramite funzioni come os.path.isabs() e os.path.normpath(). In particolare:
– os.path.isabs() può non considerare alcuni percorsi UNC o forme particolari come assolute in versioni più vecchie di Python.
– La normalizzazione del percorso può non rimuovere o non gestire correttamente caratteristiche rilevanti ai fini della sicurezza.
Se safe_join si affida a queste funzioni per determinare la “sicurezza” del percorso senza controlli aggiuntivi, si possono generare percorsi considerati validi dalla libreria ma che, lato sistema operativo, hanno una semantica diversa.
4. Vettore di attacco tipico
Un possibile scenario di attacco su un’app Flask/Werkzeug che espone un endpoint di download potrebbe essere:
`python
@app.get(“/download”)
def download_file():
filename = request.args.get(“file”)
safepath = safejoin(BASE_DIR, filename)
if safe_path is None:
abort(400)
return sendfile(safepath)
`
Se safe_join non valida correttamente i segmenti su Windows, un attaccante potrebbe passare valori come:
– CON.txt
– AUX
– combinazioni con directory intermedie o caratteri di traversal.
Il percorso risultante potrebbe:
– superare i controlli di safe_join;
– essere interpretato dal sistema come accesso a un device o a un percorso non previsto.
Anche se l’effetto immediato può variare (lettura, blocco, comportamento inatteso), dal punto di vista della sicurezza si tratta di una violazione del confine logico imposto dalla directory base.
5. Strategie di mitigazione per sviluppatori
Oltre all’aggiornamento di Werkzeug alla versione più recente, è consigliabile:
- Implementare un livello di validazione applicativa prima di chiamare
safe_join:
- Implementare un livello di validazione applicativa prima di chiamare
– rifiutare segmenti che contengono ..;
– rifiutare segmenti che iniziano con \\ o simili pattern UNC;
– rifiutare in modo esplicito i device names Windows (anche con estensioni o spazi finali).
- Applicare una whitelist di pattern ammessi per i nomi file:
– ad esempio, solo [A-Za-z0-9_.-] per il nome, senza spazi finali;
– estensioni limitate (es. solo .jpg, .png, .pdf).
- Non esporre percorsi arbitrari agli utenti:
– invece di far passare il percorso completo, usare identificatori logici (ID di database, token random) e mappare questi ID ai percorsi reali lato server.
- Separare i ruoli di lettura e scrittura:
– usare un account di sistema dedicato e con privilegi minimi per il processo dell’applicazione;
– montare eventuali share o directory sensibili in modo che non siano accessibili all’utente del processo.
6. Considerazioni per ambienti misti (Windows + altri OS)
Se la stessa applicazione gira sia su Windows che su Linux/macOS:
– testare esplicitamente i comportamenti di safe_join e delle funzioni di path su tutte le piattaforme supportate;
– attivare test automatici di sicurezza per path traversal con casi specifici per Windows (UNC, device names, spazi finali, caratteri speciali).
In molti casi, può valere la pena:
– astrarre l’accesso ai file in un modulo dedicato;
– centralizzare lì tutte le difese (whitelist, controlli sui device names, log, ecc.);
– evitare che logica applicativa generica si interfacci direttamente con il file system.
7. Raccomandazioni operative finali
Per sistemi in produzione che usano Werkzeug su Windows:
– Mappa dell’esposizione: individua tutti i punti dell’applicazione che:
– leggono o scrivono file usando percorsi derivati da input utente;
– usano safe_join o logiche analoghe.
– Priorità di intervento: dai priorità agli endpoint accessibili da Internet e a quelli che trattano dati sensibili o credenziali.
– Logging e monitoraggio:
– abilita log dettagliati sui percorsi richiesti;
– monitora tentativi sospetti (ad esempio molti .., CON, AUX, percorsi UNC).
Applicando queste misure, uno sviluppatore può non solo mitigare la vulnerabilità specifica di safe_join su Windows, ma anche creare una base più solida contro l’intera classe di attacchi di path traversal.
Fonte: https://github.com/pallets/werkzeug/security/advisories/GHSA-97p3-p365-5ph6





