Come scrivere una solida implementazione TOTP?

3

Attualmente sto scrivendo un'implementazione TOTP in PHP (ma questo vale anche per altre lingue) e, naturalmente, voglio che sia il più sicuro possibile, che cosa dovrebbe essere considerato?

Dopo aver letto la RFC 6238 e RFC 4226 attualmente la mia implementazione è simile a questa:

  • Ogni singolo codice utilizzato è in blacklist per 2 minuti, indipendentemente dal fatto che sia stato eseguito correttamente o meno
  • Il segreto è generato da un generatore di numeri casuali sicuro
  • Il codice QR viene generato sulla mia macchina e non viene consegnato a provider di terze parti
  • È necessario entrare in un reCaptcha per prevenire attacchi di forza bruta
  • I codici sono convalidati utilizzando una funzione di confronto resistente all'attacco di tempo
  • Vengono controllati un totale di 5 codici (l'attuale, gli ultimi due e i successivi due)
  • Viene generato un singolo codice di salvataggio di 16 caratteri (da un generatore di numeri casuali sicuro) e visualizzato solo una volta dopo l'attivazione, non può essere recuperato dall'utente in seguito
  • Gli utenti vengono richiesti solo una volta ogni sette giorni su una macchina conosciuta (impostando un cookie)
  • I codici di Secrets and Rescue sono memorizzati in modo non criptato nel database, ma questo non dovrebbe essere un problema in quanto lo script deve comunque decrittografarlo

Mi mancano alcuni importanti? Alcuni punti sono una pessima decisione?

    
posta TimWolla 02.01.2014 - 20:30
fonte

3 risposte

2

Users are asked only once every seven days on a known machine (by setting a cookie)

Dovrai stare molto attento qui, in quanto un tale cookie sarebbe effettivamente una backdoor bypassando il requisito dei 2 fattori. Un utente malintenzionato dovrebbe attendere fino a quando un utente esegue l'autenticazione, ruba il suo cookie e ora non è più necessario preoccuparsi dell'autenticazione a 2 fattori. Puoi potenziarlo legando il cookie all'indirizzo IP (molto inaffidabile, dal momento che la gente salta sempre i provider wireless), a una stringa ID del browser (molto facile da sconfiggere) oa una regione GeoIP (più affidabile che a una IP, ma anche meno sicuro e non infallibile.

FYI, ho scritto un'implementazione TOTP Python / CGI ( link ), che accetta semplici chiamate REST. Potrebbe essere qualcosa che puoi usare invece di riscriverlo interamente in PHP.

    
risposta data 02.01.2014 - 21:39
fonte
3

Si potrebbe obiettare che i segreti non cifrati, archiviati "così come sono" nel database, potrebbero essere una facile preda agli attacchi di SQL injection. Sebbene concettualmente i segreti siano comunque accessibili dal server in esecuzione, potrebbe essere utile proteggerli un po 'di più, in modo che gli aggressori debbano andare oltre lo stadio "SQL personalizzato". Ad esempio, invece di memorizzare il S segreto e il codice di salvataggio C per ogni utente nel database, memorizzare per ciascun utente un valore casuale R e calcola il S segreto e il codice di salvataggio C con HMAC su R , utilizzando una chiave segreta a livello di server memorizzato in un file di configurazione, non nel database. Usa HMAC / SHA-1 su "secret || R " (concatenazione della stringa ASCII " secret " e il valore casuale R ) per ottenere l'effettivo segreto dell'utente S ; per il codice di salvataggio, utilizzare HMAC / SHA-1 su "rescue || R ".

Altre persone potrebbero obiettare che PHP non è la lingua migliore per la crittografia. In effetti, i linguaggi di alto livello non sono adatti per cose come "funzioni di confronto a tempo costante". Per ottenere un controllo reale sui problemi di implementazione (tutte le fughe di canali laterali, compresi i tempi), è consigliabile un linguaggio di livello inferiore (anche C # o Java sarebbero "di livello inferiore" in tal senso).

La lista nera di tutti i codici inviati può aumentare la vulnerabilità a DoS; qualcuno potrebbe inviarti spam con molte richieste in modo da far ricordare al tuo server molti codici in blacklist. Allo stesso modo, la tua descrizione non sembra includere misure di prevenzione di nuovo spam così pesante. Potresti, almeno, rifiutarti di parlare con gli indirizzi IP che ti hanno inviato più di dieci richieste negli ultimi dieci secondi circa.

L'implementazione corretta della crittografia è difficile; farlo di nuovo significa assumersi rischi aggiuntivi di problemi relativi all'implementazione. Fare il tuo codice è una grande pedagogia; ma se vuoi utilizzare il codice in produzione, forse dovresti prima provare a vedere se non esiste un'implementazione esistente che sia già adatta al tuo conto.

    
risposta data 02.01.2014 - 21:11
fonte
0
  • Every single used code is blacklisted for 2 minutes, independent of whether it was successful or not
  • A total of 5 codes are checked (the current, the last two and the next two)

È un thread vecchio ma, nel tuo caso, i codici utilizzati dovrebbero essere inseriti nella lista nera per 6 (the codes that you allow + 1) * time step (ad es., 30 o 60 secondi) che hai usato per generare il codice. Altrimenti sarà comunque possibile per qualcuno autenticare con un codice già utilizzato.

È importante che il tuo trasporto non sia protetto e che qualcuno possa intercettare

    
risposta data 30.01.2017 - 20:23
fonte

Leggi altre domande sui tag