Il recente incidente di sicurezza che ha interessato la popolare applicazione di messaggistica aziendale Slack ha prepotentemente portato in primo piano l’importanza di una corretta gestione delle password.
In particolare, è fondamentale prevedere una memorizzazione sicura delle password utilizzando correttamente gli algoritmi crittografici di hash di cui spesso si sente parlare (basta citare alcune sigle come MD5 o SHA-1/2/3 per capire di cosa stiamo parlando), ma di cui poco si conosce relativamente al loro funzionamento e alla loro utilità.
I 10 migliori password manager: cosa sono, come usarli e perché sono utili anche alle aziende
Indice degli argomenti
Incidente di sicurezza a Slack: il fatto
Slack, la popolare applicazione di messaggistica aziendale, ha recentemente reso noto di aver forzato il reset delle password dello 0,5% dei suoi utenti per sanare un bug di sicurezza che era presente dal 2017 e che ora dovrebbe essere stato risolto.
Secondo quanto comunicato dalla stessa azienda, il bug in questione si verificava quando gli utenti creavano o revocavano un link di invito condiviso per il loro spazio di lavoro. Quando un utente eseguiva una di queste azioni, Slack trasmetteva una versione hash della sua password agli altri membri dello spazio di lavoro. Questa password in forma di hash non era visibile a nessun client Slack; per scoprirla era necessario monitorare attivamente il traffico di rete crittografato proveniente dai server di Slack.
Il bug è stato scoperto da un ricercatore di sicurezza indipendente ed è stato comunicato a Slack il 17 luglio 2022. Il problema riguardava tutti gli utenti che avevano creato o revocato collegamenti a inviti condivisi tra il 17 aprile 2017 e il 17 luglio 2022.
Slack ha dichiarato che, dopo aver ricevuto la segnalazione, ha immediatamente risolto il bug e ha indagato sul suo potenziale impatto per gli utenti.
Sebbene non sembri trattarsi di una vulnerabilità grave (non dovrebbe essere stato possibile che qualche malintenzionato sia stato in grado di ottenere password in chiaro a causa di questo bug), per prudenza Slack ha – come detto – resettato le password Slack degli utenti interessati. Non è stato chiarito quali siano questi utenti, se non che sia tratta dia una minima parte pari allo 0,5% e che questi dovranno impostare una nuova password Slack prima di poter accedere nuovamente all’applicazione.
Questa vicenda, che non sembra avere avuto gravi impatti, ci offre dunque lo spunto per evidenziare l’utilità e l’importanza degli algoritmi di hash, il cui uso è poco conosciuto e talvolta gravemente sottovalutato.
Cosa sono gli hash
In informatica, hash è una classe di algoritmi crittografici che trasformano un dato di lunghezza arbitraria (messaggio) in una stringa binaria (detta “digest”) di lunghezza fissa, lunghezza che varia a seconda dell’algoritmo di hash utilizzato.
Il termine hash deriva dall’inglese “sminuzzare, pasticciare”.
La peculiarità dell’hash è quello di essere non invertibile (one-way): dall’hash non è mai possibile risalire al valore iniziale.
Questa è una differenza sostanziale rispetto agli altri algoritmi di crittografia simmetrica (AES) e asimmetrica (RSA ecc.) che invece sono reversibili: dal messaggio originale (messaggio in chiaro) si genera un testo cifrato e da questo con l’algoritmo deputato alla decodifica si ritorna al messaggio originale, a condizione di conoscere la chiave (o le chiavi) di codifica e decodifica.
Questa decodifica non è possibile con gli algoritmi di hash.
È importante avere chiaro che il risultato della funzione di hash restituirà sempre una stringa alfanumerica rappresentata da un numero fisso di caratteri, indipendentemente dalla dimensione dell’input.
Se facessimo l’hash della Divina Commedia, ad esempio, il risultato sarebbe sempre una stringa di 32, 40 o 64 caratteri. La lunghezza dell’output dipende solo dalla funzione di hashing usata.
È quindi evidente che l’hash non è il file compresso (zippato), non contiene l’intero file, ma solo la sua impronta digitale (fingerprint).
Algoritmi crittografici, dal NIST i primi quattro resistenti ai computer quantistici: i dettagli
I principali algoritmi di hash
Sono stati sviluppati negli anni molti algoritmi di hash, con complessità sempre maggiore per essere resistenti alla crescente potenza dei computer.
Li elenchiamo in ordine cronologico:
- MD5 (“Message Digest”): genera una fingerprint da 128 bit (32 caratteri esadecimali). Sviluppato da Ronald Rivest nel 1991, è ormai considerato non più sicuro, sebbene sia ancora utilizzato;
- SHA-1 (“Secure Hash Algorithm 1”): genera una fingerprint da 160 bit (40 esadecimali). Nato nel 1995, è considerato non più sicuro, dopo che Google ne ha dimostrato la possibilità di collisione;
- SHA-2 (“Secure Hash Algorithm 2”): nato nel 2001, è la variante più sicura di SHA-1, con dimensioni dell’hash maggiori, da 256 (64 esadecimali) a 512 bit (128 esadecimali);
- SHA-3: è stato definito dal NIST con la FIPS PUB 202 (agosto 2015) ed è destinato a diventare il nuovo standard.
Esistono molti altri algoritmi di hash, tra i quali citiamo: bcrypt, ripemd256, haval128,4 e gost-crypto.
Le caratteristiche e i requisiti
Qualunque algoritmo di hash deve rispondere a questi requisiti imprescindibili e mandatori:
- non invertibile: dall’hash – come abbiamo già spiegato – non è mai possibile risalire al valore iniziale;
- coerente: deve generare un risultato univoco. Quindi l’input A produrrà sempre lo stesso hash B, che rappresenta la fingerprint (impronta digitale) di A;
- impossibile da interpretare: dall’hash deve essere impossibile capire qual è il messaggio originale, si ha solo la certezza che – se l’hash è lo stesso – anche l’originale deve essere lo stesso. Questa indecifrabilità dell’hash è evidente nella sua caratteristica, conosciuta come “effetto valanga”: una minima variazione del dato in input genera un risultato di hash totalmente diverso. Nelle due tabelle seguenti vediamo un esempio del cosiddetto effetto valanga. Nella prima abbiamo calcolato – con tre differenti algoritmi – l’hash di “Giorgio Sbaraglia”. Nella seconda tabella abbiamo fatto la stessa cosa, modificando una sola lettera nei dati di input: “Giorgio Sbaragli”. Si vede come i risultati degli hash siano completamente differenti.
MD5 | 54e9cd53 2d100cab a8d2e2c4 073319fc | 32 esadecimali (128 bit) |
SHA1 | 9f236c78 bb1f22a5 044dd57a 25214020 719da5a0 | 40 esadecimali (160 bit) |
SHA256 | 35c6507d 54b22a07 289ab985 318047a4 bc196e6b 23401f68 fd0d4cf3 2b08deb0 | 64 esadecimali (256 bit) |
MD5 | 31164965 c4d73361 4c46dfb2 b2932b1b | 32 esadecimali (128 bit) |
SHA1 | 51fc1f4b 1576e7e6 62dd63ed 265fca98 ace753fa | 40 esadecimali (160 bit) |
SHA256 | 2a04c3ec 646ab006 86cf2f53 1262625e b2a66aec 958e9261 b85f014d 1d07429a | 64 esadecimali (256 bit) |
- univoco: la probabilità che due messaggi (o file) diversi generino lo stesso hash deve essere nulla. Questa caratteristica si definisce “resistenza alle collisioni”. Una collisione si verifica quando due input distinti – un documento, un file binario o il certificato di un sito web – producono lo stesso hash come risultato. Le collisioni non dovrebbero mai verificarsi per le funzioni hash sicure.
In realtà, la “resistenza alle collisioni” non può essere garantita a priori perché qualunque algoritmo di hash può generare un numero finito di risultati, quindi la resistenza alla collisione è direttamente proporzionale alla complessità dell’algoritmo. Non è impossibile, a certe condizioni.
In crittografia, con il termine “impossibile” si intende un processo non realizzabile con gli strumenti computazionali disponibili. Al crescere della potenza computazionale l’impossibile può diventare possibile.
Questo è un tema da tenere sempre presente nella crittografia moderna.
Ne abbiamo un esempio con la comparsa dei computer quantistici che stanno rendendo non più inviolabili gli attuali algoritmi crittografici ed è quindi nata la necessità di creare nuovi algoritmi resistenti ai computer quantistici: ne abbiamo parlato in questo articolo.
Ritorniamo agli algoritmi di hash e vediamo un esempio: SHA-1 produce sempre una stringa di 160 bit. Dunque i possibili risultati di hash per SHA-1 sono pari a 2160, un valore enorme, ma comunque un numero finito.
I valori in entrata sono invece in numero infinito, quindi è possibile trovare due stringhe che producono lo stesso hash: questo diventa più facile all’aumentare delle potenze computazionali disponibili.
Ed è esattamente quello che ha fatto Google: nel febbraio 2017, a più di 20 anni dall’introduzione di SHA-1, ne ha dimostrato la collisione. Dopo due anni di ricerche condotte in collaborazione con il CWI Institute di Amsterdam, Google ha pubblicato, come prova dell’attacco, due PDF con hash SHA-1 identici ma con contenuti diversi.
Per aumentare la resistenza alle collisioni si rende necessario utilizzare algoritmi di hashing più potenti, cioè con un maggior numero di bit: SHA-2 genera una stringa a 256 o 512 bit, quindi le combinazioni possibili sono rispettivamente 2256 e 2512 (quest’ultimo è pari a 1,3×10154), numeri esponenzialmente molto più grandi di quelli generati da MD5 e da SHA-1.
A cosa servono gli hash
Gli hash sono una sorta di “impronta digitale” (fingerprint) a lunghezza fissa di un messaggio/file. Trovano numerose applicazioni anche al di fuori dalla crittografia:
- controllo degli errori (“checksum error”): verifica di integrità durante la copia, errori di trasmissione o scrittura, ecc.;
- verifica dell’integrità di un messaggio: per garantire che un messaggio non sia stato modificato da un eventuale attaccante. Si controlla l’hash del messaggio, non l’intero messaggio, confrontando quello in partenza con quello in arrivo;
- firme digitali: firmare l’intero documento è computazionalmente pesante, quindi si calcola l’hash del documento e la firma digitale si applica solo all’hash;
- blockchain e criptovalute;
- identificativo di file o dati: per identificare un file senza doverlo salvare o analizzare per esteso. Questa tecnica è utilizzata dai software antivirus “signature based”, basati appunto sulla firma, cioè sull’hash del file da controllare. Sempre gli hash servono ad individuare in modo univoco gli indicatori di compromissione (IoC) che identificano un file malevolo;
- copia forense di un documento, disco ecc.;
- memorizzazione di password: la password non viene salvata in chiaro per motivi di sicurezza, viene cifrata per evitare che sia possibile risalire alla password originale. Si memorizza in questi casi l’hash della password.
Uso degli hash nella memorizzazione delle password
Uno degli impieghi più frequenti delle funzioni di hash si ha nella memorizzazione delle password nei siti e servizi che richiedono un’autenticazione.
Ovviamente il servizio web deve necessariamente conservare le password degli utenti registrati, per verificarle nella fase di login.
I database contenenti queste password potrebbero essere violati e rubati da un attaccante, per questo è opportuno, anzi necessario, che le password non siano memorizzate in chiaro, ma attraverso l’hash corrispondente. In fase di login, la password digitata dall’utente verrà sottoposta ad hashing ed il risultato confrontato con l’hash precedentemente memorizzato dal sito web.
Questo è il motivo per cui, in caso di “password dimenticata”, il sito non ci potrà restituire la nostra password (perché, semplicemente, non ce l’ha), ma ci invierà un link per impostarne una nuova.
Il vantaggio di usare gli hash è evidente: se un attaccante riesce a violare il database delle password, avrà il database con gli hash e non le password in chiaro. Poiché gli hash non sono invertibili, lo dovrà fare per tentativi, utilizzando le tecniche di password cracking che abbiamo descritto in un precedente articolo: attacco brute force, a dizionario e via dicendo.
Dovrebbe quindi essere molto complicato per un attaccante dal database degli hash risalire alle password in chiaro.
L’hash delle password e le tabelle arcobaleno
Dovrebbe, ma esistono le rainbow table (tabelle arcobaleno).
Le rainbow table sono tabelle dove vengono inseriti tutti gli input possibili e ne vengono precalcolati i rispettivi hash. Sono state inventate da Martin Hellman.
Le rainbow table sono file di enormi dimensioni, anche oltre i 100 GB, che si possono trovare in rete.
Per contrastare le rainbow table e renderne più difficile l’utilizzo, si possono adottare queste contromisure:
- aumentare la lunghezza della password: in questo modo aumenteranno esponenzialmente anche le dimensioni delle “tabelle arcobaleno” che non potranno gestire l’enorme numero di combinazioni;
- aggiungere il SALT (sale) all’hash, cioè “salare l’hash”.
Password, hash e salting (il sale)
Il procedimento di salting (sale) consiste nell’aggiunta di una stringa addizionale alla password.
Questa stringa può essere generata in modo pseudocasuale prima di calcolarne l’hash: quando un utente imposta una password, il sistema crea un valore casuale aggiuntivo, il salt.
Questo valore si aggiunge in coda alla password e da tale stringa composta viene poi calcolato l’hash, che avrà un altro valore, differente da quello generato dalla sola password.
In questo modo si rendono molto più onerosi gli attacchi “a dizionario” e quelli “brute force”.
Lo scopo del salt è infatti quello di moltiplicare il numero di combinazioni hash possibili a fronte di ciascuna password.
Per una data password (che se priva del salt avrebbe un unico hash come risultato), il numero di possibili combinazioni diventa invece pari a: 2sLen dove sLen è la lunghezza del salt in bit.
Per esempio, con un salt di 32 bit il numero di hash possibili si moltiplica di un fattore pari a 232 = 4.294.967.296, ove il valore di 32 bit è la lunghezza minima consigliato dalla SP 800-63B Digital Identity Guidelines: Authentication and Lifecycle Management al cap.5.1.1.2 (ne abbiamo parlato qui).
Nella tabella sottostante vediamo un esempio di Salting con due password uguali:
password123 + salt (diverso)
Se il salt è sufficientemente lungo (almeno 32 bit) e viene variato tra le diverse password, la probabilità di successo di un password cracking su un database di hash di password si abbassa enormemente, diventando praticamente inutilizzabile.