Guida per rivedere l'algoritmo 2FA

0

Prima di tutto, lo so, non reinventare la ruota ... Ma c'è una buona ragione per questo.

Quindi ho implementato un generico algoritmo di generazione / convalida del codice di autenticazione a 2 fattori per riutilizzarlo in più applicazioni e renderlo stateless (l'algoritmo non ha bisogno di memorizzare nulla nel database, e non non richiede alcun dato utente.)

L'applicazione che utilizza il codice è responsabile di impostare un carico utile e convalidarlo all'interno del processo generico 2 fa.

Quindi ecco come funzionerebbe ...

1 - L'applicazione richiede un nuovo codice 2FA che trasmette un carico utile:

1.1 - payload: dati arbitrari, come ID utente e ID applicazione.

1.2 - Viene creato un codice casuale a 7 cifre (utilizzando librerie casuali crittografiche sicure)

1.3: viene selezionato un tempo di scadenza, ovvero 3 minuti dall'ora corrente, espresso in epoch tempo in secondi.

1.4 - dati: (scadenza, payload, codice)

1.5 - i dati vengono crittografati utilizzando CTR AES con un IV generato a caso di 128 bit e una chiave segreta

1.6 - Sia i dati crittografati che IV vengono digeriti tramite un HMAC che utilizza un'altra chiave segreta, al fine di firmare questi due valori.

1.7 - token finale: "dati crittografati base64: IV: firma"

1.8 - il token viene restituito all'interfaccia utente utente (come un'app mobile o un sito web di accesso)

1.9 - il codice viene inviato tramite SMS o Email

2 - L'applicazione invia il token originale e il codice fornito dall'utente al back-end

2.1 - il token è decodificato e la firma è validata

2.2 - Il token è decrittografato, la verifica della scadenza e il codice utente viene confrontato con il codice token

2.3 - Il carico utile viene restituito all'applicazione, che esegue qualsiasi convalida aggiuntiva come il recupero di un utente dall'ID utente nel payload, ecc ...

È rotto? Potresti chiedere perché non memorizzare solo il codice di 7 cifre nel database, ma l'idea è di renderlo completamente stateless e generico.

Nota anche: l'endpoint per la generazione / convalida di token deve essere limitato in modo che non possa essere forzato bruto.

    
posta user1777914 05.07.2018 - 19:38
fonte

2 risposte

1

Dopo averlo pensato per 15 minuti e supponendo che sia implementato correttamente e che le applicazioni che lo utilizzano lo usino correttamente, l'unico problema minore che riesco a trovare è quello della lingua:

1.8 - the token is returned to the user UI (such as a mobile app or login website)

L'interfaccia utente implica che sia presentata all'utente. L'utente non ha bisogno di vedere il token, dovrebbe essere restituito all'utente client , che lo invia senza che l'utente debba vederlo. Questo è ovviamente un problema molto minore in quanto in realtà non danneggia nulla all'utente, non è proprio necessario.

Ovviamente, probabilmente vorresti qualcuno migliore di me a pensarci per più di 15 minuti.

Personalmente mi aspetto che una volta che una percentuale abbastanza significativa di persone utilizza 2FA (e abbastanza posti supportano 2FA), i phisher inizieranno a utilizzare proxy come Evilginx , a cui sono vulnerabili le soluzioni OTP. Per quanto ne so, l'unico metodo 2FA che ora impedisce questo è U2F, che richiede l'archiviazione di una chiave pubblica per ciascun utente.

Non credo che sia possibile possibile impedire questo tipo di phishing senza memorizzare una chiave pubblica, un segreto o qualcosa di simile per utente. Se implementassi 2FA, proverei a renderlo compatibile con U2F, o almeno a provare a progettarlo in modo che U2F o un metodo futuro possano essere facilmente aggiunti, se lo desideri.

Si noti inoltre che né gli SMS né le e-mail hanno forti garanzie di non essere intercettati. Almeno con TOPT o HOTP potresti usare qualcosa come Google Authenticator che, pur essendo ancora vulnerabile contro un proxy malevolo, almeno non deve inviare un codice che potrebbe essere intercettato.

    
risposta data 05.07.2018 - 23:44
fonte
0

Sembra "Non voglio camminare per un chilometro, quindi percorrerò invece cento chilometri" . Salvare sette numeri in un database, o un file piatto, o qualsiasi cosa è molto più semplice, e anche generico. La tua soluzione non è stateless, poiché lo stato viene inviato al client.

Non userò sicuramente il tuo sistema, è pieno di parti mobili. Se invierai un token all'utente tramite e-mail o SMS, salvalo e confrontalo in un secondo momento. È sufficiente un piccolo database SQLite e ci sono librerie per usarlo in quasi tutte le lingue. Avresti un database come questo:

[userid | token   | expiration         ]
|192    | 1234567 | 2018-07:15 10:11:12|
|723    | 7482912 | 2018-07:15 15:24:33|
----------------------------------------

Per evitare che il database diventi troppo grande, puoi eseguire un lavoro ogni ora circa per eliminare i token scaduti.

Puoi semplificare un po 'il sistema e liberarti del lavoro di pulizia utilizzando un TOTP appropriato. . Creare un database con l'ID utente e la chiave. Quando l'utente vuole autenticare, chiedi il token. L'utente aprirà Google Authenticator, Authy , 1Password , Enpass o qualsiasi altro client TOTP che utilizza. Quando l'utente invia il token, calcola e convalida il token. Sono disponibili anche molte librerie TOTP, per quasi tutte le lingue.

Per utilizzare il secondo approccio, aggiungerai alla tua applicazione solo un piccolo database SQLite e una libreria. Penso che il sovraccarico sia molto piccolo e semplifica molto il tuo processo.

    
risposta data 05.07.2018 - 22:30
fonte

Leggi altre domande sui tag