Token di verifica dell'autenticazione basata sul tempo

5

Sto costruendo un sistema di sessioni di lunga durata che richiede che gli utenti verifichino la loro autenticazione prima di eseguire operazioni "pericolose", come cambiare le impostazioni critiche, cancellare il loro account, ecc. Questo requisito è analogo a Facebook che richiede di rientrare la tua password prima di cambiare il tuo indirizzo email, per esempio. Vorrei consentire all'utente di apportare modifiche pericolose entro un certo periodo di tempo T dopo aver verificato la password.

Il sistema si ridimensiona orizzontalmente, quindi non è possibile ricordare "chi ha convalidato quando" in memoria e vorrei evitare di memorizzare le informazioni nel database e cercarlo in ogni azione "pericolosa". Credo che le foglie generino un certo fattore di sicurezza% time-sensitive come la mia migliore alternativa.

Ecco il mio approccio per generare e verificare questo token, per favore fatemi sapere se pensate che abbia trascurato qualcosa, o sto facendo un errore di sicurezza insensato. Tutte le comunicazioni client-server sono su TLS / SSL.

1. Alice wants to perform some "dangerous" operation (client side).
2. Alice is presented with a "verify password" modal or similar UI element
   where she enters her password.
3. The client-side system sends the password to the server.
4. The server checks if the password matches Alice's stored password.
5. If the passwords match, a token is generated as follows:
   a. Let 'id' be Alice's user ID (UUID), 't' be a fixed length 
      string representation of the current timestamp, and 'secret' 
      be a secret key appropriately protected on the server.
   b. Generate the secure part as 'k = (string) HMAC(secret, id + t)' 
      (Assume 'k' to be typecasted or converted to a string representation.)
   c. Finally, let 'token = k + t' where '+' is the string concatenation
      operator 
6. Send the token to Alice.
7. For each "dangerous" operation, Alice includes 'token' with the request. 
8. The server can verify the 'token' by splitting 'k' and 't' and
   validating 'k' as in step 5.b above, and verify that time 'T' hasn't
   elapsed since Alice verified her password.

Credo che questo approccio risolva il problema. Suggerimenti? Mi manca qualcosa?

    
posta Joshua Toenyes 17.06.2016 - 18:41
fonte

2 risposte

4

Suggerirei di creare invece un timestamp di precisione ridotta, in cui si imposta la precisione come metà della precisione desiderata. La ragione di ciò è sia di evitare di inviare più dati di quelli necessari al client, il che aumenta la sicurezza, ma anche di filtrare i dati sul lato server in modo più efficace, per evitare attacchi che insorgono da non sicuri / input contaminato.

Quindi, ad esempio, se vuoi che il token vivi per 10 minuti, fai un timestamp che cambierà in modo critico una volta ogni 5 minuti.

Usando un timestamp standard di unix, dividi questo con il mezzo numero di secondi per il quale vuoi che il token sia vivo e togli il decimale.

Quindi 1466182513, che è l'ora corrente. Dividilo con 300 (5 minuti) e int () esso. Ottieni: 4887275

che sarà valido da:

Ven, 17 giu 2016 16:55:00 GMT

a

Ven, 17 giu 2016 16:59:59 GMT

Questo valore decimale può essere incluso nell'hash. Quindi il valore 4887275 è effettivamente un "orologio" che "spunta" ogni 5 minuti.

Ora per il trucco: Quando si verifica l'hash, si "prova" con il valore a precisione ridotta per il tempo CORRENTE, ma anche il valore a precisione ridotta immediatamente precedente. Ciò significa che il cliente sarà in grado di eseguire "azioni sensibili" da 5 a 10 minuti dal momento in cui inserisce la password.

Non fraintendetemi ora. Quello che voglio dire è che il token scadrà tra i 5 e i 10 minuti dall'emissione, e questa scadenza dipenderà da quando, nel tempo, immetteranno la password.

Ad esempio, nell'esempio sopra, provate a convalidare l'hash sia con il valore 4887275, che è dall'ora corrente, sia con il valore 4887274, che è il valore di circa 1-5 minuti fa.

Naturalmente, puoi dividere con altri valori per ottenere altra precisione, ad esempio 600 per ottenere una validità compresa tra 10 e 20 minuti.

La ragione per cui dovresti provare anche il timestamp immediatamente prima, è che, diciamo che una persona immette la sua password a Ven, 17 Jun 2016 16:54:59. Ora ha 1 secondo per eseguire la sua azione sensibile, a meno che non proviamo anche il valore immediatamente prima. Ecco perché è necessario selezionare un valore mezzo della precisione desiderata.

Questo significa che non è necessario inviare il timestamp al client. Devi semplicemente inviare l'hash, poiché puoi facilmente ricostruire TUTTI i dati nell'hash.

Una buona idea è anche quella di includere l'ID di sessione nell'hash, quindi il token viene effettivamente invalidato non appena l'utente si disconnette o la sessione viene distrutta per qualche altro motivo. Anche l'hash della password è una buona idea da includere, quindi se l'utente cambia la sua password, qualsiasi token diventa non valido.

    
risposta data 17.06.2016 - 19:09
fonte
0

Kerberos è un protocollo efficace che può essere utilizzato per fare ciò. I dettagli possono essere trovati qui: link . Tuttavia richiede un po 'di configurazione.

È un metodo di autenticazione e autorizzazione sensibile al tempo. Fondamentalmente, si ottiene un Ticket-Granting-Ticket dal server di autenticazione e questo viene presentato al servizio di concessione ticket per ottenere un ticket che può essere utilizzato per ottenere l'autorizzazione a un servizio specifico. Quando questo servizio viene presentato con il ticket, autorizza l'utente a eseguire qualsiasi servizio fornito dal server per il ticket. Se il ticket è scaduto, devi ottenere un nuovo ticket dal TGS.

Al TGS può essere richiesto di verificare la password dell'utente prima di fornire il ticket che autorizza l'utente a effettuare tali modifiche. Alla scadenza del ticket, l'utente dovrà eseguire di nuovo l'autenticazione per ottenere un nuovo ticket.

    
risposta data 17.06.2016 - 19:14
fonte

Leggi altre domande sui tag