L'algoritmo MD5 e le analisi di sicurezza del codice
Sì è vero, l'MD5 non è affatto sicuro e non dovrebbe oramai essere più utilizzato. O no?
Analizzando delle review di sicurezza di codice sorgente di portali Web 2.0, mi sono imbattuto in considerazioni che mi hanno fatto riflettere. Il reviewer aveva infatti classificato tutte le invocazioni della funzione MD5 come pericolose. Ma siamo davvero sicuri che quelle invocazioni all'MD5 fossero sempre insicure?
In alcune applicazioni sottoposte alla review, l'MD5 veniva infatti utilizzato come algoritmo per la generazione di ID univoci: sessioni, token, nomi di file temporanei. Quasi sempre l'input passato alla funzione hash era quindi una stringa casuale, creata da un generatore di numeri random e a partire da un certo seed.
Riepilogo brevemente qui di seguito le proprietà delle funzioni hash crittografiche:
- Unidirezionalità: dato H è arduo determinare M tale che H=hash(M). In poche parole si dice che la funzione H non è invertibile.
- Resistenza debole alle collisioni: dato M1 è arduo determinare M2 tale che H(M1) = H(M2).
- Resistenza forte alle collisioni: è arduo trovare una coppia (M1,M2) tale che H(M1) = H(M2).
- Sia M1 e M2 una piccola variazione di M1, allora H(M1) e H(M2) sono molto diversi tra loro.
sappiamo però che la debolezza dell'algoritmo MD5 è proprio nella possibilità oggi di trovare "collisioni" in un tempo ragionevole. Quindi è possibile trovare due testi M1 e M2, diversi tra loro, tali che MD5(M1)=MD5(M2).
Assumendo quindi di conoscere l'ID univoco generato dall'applicazione, dove ID = MD5(rnd(seed1)), dovremmo trovare un numero "N1" tale che ID = MD5(N1). Ovvero N1 sarebbe una collisione di rnd(seed1). Ma noi non conosciamo rnd(seed1) e anche conoscendolo ci faremmo ben poco! Dovremmo infatti da N1 trovare una qualche relazione con "seed1" e tentare di predire il prossimo ID numerico utilizzato dall'applicazione! Ecco quindi che la debolezza dell'MD5 nel caso di ID univoci ha ben pochi effetti.
Diverso è il caso in cui l'MD5 venga utilizzato per calcolare le cosiddette "impronte" o "fingerprint" di dati ben conosciuti come password e documenti. Nel primo caso l'hash serve per non memorizzare mai le password in chiaro, bensì solo gli hash corrispondenti (che le rappresentano in modo univoco). Nel secondo caso l'hash serve per determinare la firma digitale dell'impronta che rappresenta in modo univoco il testo originale. In questi casi il fatto di trovare delle collisioni in un tempo ragionevole è sì un vero problema. Infatti conoscendo l'hash e il documento originale, potremmo generare un documento equivalente di cui l'hash ne rappresenterebbe comunque l'impronta (vedasi i certificati falsi con fingerprint valido). Nel caso di password e hash vi rimando invece ad un mio post passato.
Riepilogando: nel caso in cui l'MD5 venga utilizzato per generare "impronte" o "firme" di dati allora il fatto di trovare facilmente delle collisioni costituisce un serio problema. Nel caso invece in cui l'MD5 venga utilizzato per "aumentare(*) e normalizzare" la casualità di stringhe già casuali (token, sessioni, ID) forse non dovremmo disperarci poi tanto.
Intendiamoci : se dovete sviluppare una nuova applicazione è buona norma utilizzare le migliori tecnologie disponibili, ma nel caso di grosse applicazioni Web con una storia ed una manutenzione complessa allora dovrete valutare se il gioco (la sostituzione con altro algoritmo hash), vale la candela (l'incremento di sicurezza corrispondente).
(*) nessuno ci garantisce che le funzioni hash crittografiche siano anche generatori di numeri casuali (ovvero con una distribuzione di probabilità equamente distribuita per tutte le occorrenze generate) ma sovente vengono utilizzate anche a questo scopo. Se però una funzione hash crittografica "preferisse" alcune stringhe rispetto ad altre vorrebbe dire che le proprietà di resistenza debole e forte alle collisioni in alcuni casi potrebbero risentire di tale caratteristica. Se per assurdo una certa stringa fosse generata dalla funzione hash con probabilità 0.5 allora (congettura) sarebbe più alta la probabilità di trovare due messaggi che falsifichino la resistenza alle collisioni. Ma questo non è possibile per le proprietà delle funzioni hash. Sarà vero? :-)
Commenti
Posta un commento