Il reset della password è un login che salta la password, quindi ogni controllo presente nel modulo di login deve essere replicato o sostituito in modo deliberato. Se il percorso di reset è più debole di quello di login, un attaccante lo sfrutterà. L'OWASP Forgot Password Cheat Sheet definisce questa funzione «una fonte comune di vulnerabilità», con la user enumeration come esempio più noto.
Perché il flusso di reset è il punto debole
Un login riuscito produce una sessione. Secondo le linee guida OWASP sulla gestione delle sessioni, l'ID di una sessione autenticata equivale, temporaneamente, al metodo di autenticazione più forte utilizzato dall'applicazione. Un reset che termina con una sessione, o con una password scelta dall'attaccante, consegna la stessa cosa.
NIST SP 800-63B-4 richiede, a livello AAL2, la prova del possesso e del controllo di due fattori di autenticazione distinti. Se il login chiede due fattori, un reset che richiede un solo token inviato via email è un modo per aggirarli con un singolo fattore. L'estratto su cui ci basiamo non tratta il recupero; il documento completo contiene una sezione dedicata alla gestione degli eventi dell'autenticatore.
La nostra regola: su un account con un secondo fattore registrato, si richiede quel fattore o un codice di recupero salvato prima di accettare la nuova password, e non si permette mai che un reset rimuova o sostituisca il fattore.
La fase di richiesta
Rispondere in modo identico sia che l'account esista sia che non esista. Basta un messaggio come «Se questo indirizzo è registrato, abbiamo inviato un'email».
Anche i tempi di risposta rivelano informazioni. Un handler che termina subito per gli indirizzi sconosciuti e invia una email per quelli noti mostra la differenza, a prescindere dal messaggio. Eseguire la stessa logica per ogni richiesta, oppure affidare l'invio della email a un job asincrono.
Aggiungere un rate-limiting per account, un CAPTCHA o un controllo analogo. In assenza di tali misure, un attaccante può inviare migliaia di richieste di reset all'ora verso un singolo account e sommergere la casella email o gli SMS della vittima. Non bloccare né modificare l'account in seguito a una richiesta.
Il token
OWASP chiede quattro cose a un token o a un codice:
- che sia generato con un algoritmo casuale crittograficamente sicuro;
- che sia abbastanza lungo da resistere al brute force;
- che sia conservato in modo sicuro;
- che sia monouso e scada dopo un periodo adeguato.
Il cheat sheet non indica valori per lunghezza o durata. Il numero più vicino nelle fonti si trova nelle linee guida sulle sessioni: un CSPRNG con almeno 128 bit di entropia, preferibilmente 160 bit o più. È scritto per i token di sessione; noi lo applichiamo ai token di reset. Per la durata, scegliere un valore breve, metterlo per iscritto e testare rispetto a esso.
«Conservato in modo sicuro» può essere inteso in senso rigoroso. Se nel Suo threat model rientra la divulgazione in sola lettura dell'archivio dei token, le linee guida sulle sessioni descrivono una separazione tra identificativo e verifier segreto. Il server conserva l'identificativo pubblico di ricerca e l'hash SHA-256 completo del verifier, e confronta gli hash in tempo costante. L'identificativo da solo non deve mai valere come prova. L'applicazione di questo schema ai token di reset è un nostro suggerimento.
Consegnare il token attraverso un canale separato, email o SMS, mai nella risposta del browser. Un token nell'URL è la soluzione più semplice, ma le linee guida sulle sessioni avvertono che gli ID negli URL possono trapelare tramite link e log, cronologia del browser e segnalibri, header Referer e motori di ricerca. Tenere contenuti di terze parti e link in uscita fuori dalla pagina di reset chiude soltanto la fuga via Referer. Per il resto, scambiare il token alla prima richiesta con uno stato temporaneo lato server, reindirizzare a un URL pulito ed escludere dai log di accesso la query string di quella prima richiesta.
La fase di reset
- Far digitare due volte la nuova password all'utente e verificarla con la stessa policy della registrazione.
- Calcolarne l'hash con lo stesso codice usato per tutte le altre password.
- Invalidare tutti i token di reset ancora pendenti per l'account quando cambia la password o l'indirizzo email. In caso contrario, una vecchia email ancora presente in una casella può resettare di nuovo l'account.
- Inviare all'utente una email per comunicare che la password è cambiata. Non inserire mai la password nel messaggio.
- Indirizzare l'utente al normale login invece di autenticarlo automaticamente. Il login automatico aggiunge codice di gestione delle sessioni e, con esso, la possibilità di nuove vulnerabilità.
- Terminare le sessioni esistenti, o almeno offrire di farlo.
Dopo una sospetta compromissione, la sessione attiva dell'attaccante sopravvive al cambio di password se non viene terminata. Noi renderemmo l'invalidazione il comportamento predefinito.
MFA e account compromessi
Un semplice reset della password può non bastare a ripristinare il controllo. L'attaccante potrebbe avere ancora una sessione attiva, oppure aver modificato le informazioni di recupero o i metodi MFA.
OWASP indica di non fare affidamento esclusivo su informazioni di recupero aggiunte o modificate di recente. Utilizzare prove indipendenti stabilite in precedenza, come i codici di recupero salvati, in una combinazione che soddisfi i requisiti di assurance dell'account. Il reset dell'MFA ha una sezione dedicata nel Multifactor Authentication Cheat Sheet di OWASP, quindi conviene tenere quel processo separato dal flusso della password.
L'OWASP Authentication Cheat Sheet tratta anche la modifica di un indirizzo email registrato, aspetto rilevante perché un indirizzo cambiato reindirizza ogni reset futuro.
Testare il flusso
| Test | Esito positivo |
|---|---|
| Indirizzo esistente e indirizzo inesistente | Stesso messaggio e stesso status code |
| Serie automatizzata di richieste per indirizzo | Le mediane dei tempi di risposta coincidono |
| Richieste ripetute per un solo account | Scatta il rate limit o il CAPTCHA |
| Richiesta di reset, poi login | Account non bloccato né modificato |
| Token usato due volte o dopo la scadenza | Il tentativo fallisce |
| Vecchio token dopo un cambio di password o email | Il tentativo fallisce |
| Pagina di reset con il token nell'URL | Nessuna richiesta a terze parti né link in uscita |
| Reset con una vecchia sessione aperta | Vecchia sessione terminata |
| Secondo fattore registrato, solo token via email (nostra regola) | Reset rifiutato |
| Risposta finale e email | Nessun login automatico, nessuna password nell'email |
Per la riga sui tempi di risposta, confrontare mediane e dispersione su molte esecuzioni. Questo test rientra in qualsiasi penetration test di un flusso di autenticazione.
Da dove iniziare
- Richiedere molte volte un reset per un account esistente e per uno inesistente. Confrontare messaggio, status code e tempo di risposta.
- Leggere il generatore di token. Verificare che usi un CSPRNG, rendere i token monouso e impostare una durata esprimibile in minuti.
- Aggiungere un rate-limiting per account o un CAPTCHA all'endpoint di richiesta e verificare che una richiesta non blocchi né modifichi mai l'account.
- Fare in modo che il reset termini le altre sessioni, invalidi i token pendenti e invii una email di notifica senza la password. Verificare che la pagina di reset non carichi nulla da terze parti.
- Prendere un account di test con MFA registrata e provare a resettarlo usando solo il token inviato via email. Verificare che il reset venga rifiutato.
- Controllare chi può resettare o rimuovere un secondo fattore, quali prove deve presentare e se il recupero tratta come non attendibili i dati modificati di recente.
