2013-03-19 11 views
21

Sto implementando un servizio Web REST utilizzando C# che sarà ospitato su Azure come servizio cloud. Poiché si tratta di un servizio REST, è senza stato e quindi non contiene cookie o stati di sessione.Implementazione token autenticazione servizio Web REST

È possibile accedere al servizio Web tramite HTTPS (certificato fornito da StartSSL.com).

Quando un utente accede con successo al servizio riceverà un token di sicurezza. Questo token fornirà l'autenticazione nelle comunicazioni future.

Il token conterrà un timestamp, un ID utente e un indirizzo IP del client.

Tutte le comunicazioni avverranno solo tramite HTTPS, quindi non sono preoccupato del fatto che il token sia intercettato e utilizzato negli attacchi di replay; il token avrà comunque una scadenza.

Poiché si tratta di un servizio pubblico, sono comunque preoccupato che qualcuno possa registrarsi con il servizio, accedere e quindi modificare il token che ricevono per accedere agli account di altri utenti.

Mi chiedo il modo migliore per proteggere il contenuto del token e verificare anche che non sia stato manomesso.

ho intenzione di fare quanto segue per fissare il token:

Il client accede con successo nel servizio e il servizio fa:

  1. generare un valore casuale e patate con SHA256 1000 volte.
  2. Generare una chiave di sessione monouso dalla chiave privata + valore casuale con hash.
  3. Hash della chiave di sessione con SHA256 1000 volte e quindi utilizzarlo per crittografare il token
  4. Utilizzare la chiave privata per firmare il token crittografato tramite RSA.
  5. Invia il token crittografato + la firma + il valore casuale con hash al client in un pacchetto JSON non crittografato.

Quando il client chiama un servizio, invia al servizio il token e la firma crittografati in un pacchetto JSON non crittografato. Il servizio sarà

  1. Ricreare la chiave di sessione dalla chiave privata + il valore casuale hash
  2. Usare la chiave privata per verificare la firma
  3. Usare la chiave di sessione hash per decifrare il token
  4. Verificare che il token non è scaduto
  5. Continuare con l'operazione richiesta ...

io in realtà non so nulla di crittografia quindi ho alcune domande:

  1. È sufficiente o eccessivo?
  2. Ho letto che per rilevare la manomissione dovrei includere un HMAC con il token. Dal momento che sto firmando con la chiave privata, ho ancora bisogno di un HMAC?
  3. Devo usare Rijndael invece di RSA?
  4. Se Rijndael è preferito, l'IV generato è necessario per decodificare? posso buttarlo via o devo inviarlo sarà il token crittografato? per esempio. Token crittografato + HMAC + IV ha cancellato il valore casuale.

Poiché tutte le comunicazioni avvengono su HTTPS, il pacchetto JSON non crittografato non è realmente non criptato fino a quando non raggiunge il client.

Inoltre, potrei voler ri-implementare il servizio in PHP in seguito, quindi tutto ciò deve essere possibile anche in PHP.

Grazie per il vostro aiuto

risposta

24

siete veramente over-thinking il token. Sinceramente, la migliore sicurezza token si basa sulla casualità, o più precisamente sull'imprevedibilità dello . I migliori gettoni sono completamente casuali. Hai ragione che una preoccupazione è che un utente modificherà il suo token e lo userà per accedere agli account degli altri. Questo è un attacco comune noto come "rubare la sessione". Questo attacco è quasi impossibile quando i token vengono generati casualmente e scaduti sul lato server. Utilizzare le informazioni dell'utente come IP e/o un timestamp è una cattiva pratica perché migliora la prevedibilità. Ho fatto un attacco al college che ha indovinato i token attivi basati su time stamp del server in microsecondi. L'autore dell'applicazione pensava che i microsecondi sarebbero cambiati abbastanza velocemente da renderli imprevedibili, ma non era così.

È necessario tenere presente che quando gli utenti si trovano dietro server proxy, a volte il proxy visualizza le proprie richieste SSL in testo semplice (per motivi di sicurezza, molti proxy eseguiranno un'ispezione approfondita dei pacchetti). Per questo motivo è bene che scadiate le sessioni. Se non lo facessi, i tuoi utenti sarebbero vulnerabili a un attacco come questo, e anche possibili XSS e CSRF.

RSA o Rijndael dovrebbero essere sufficienti, purché la lunghezza della chiave sia ragionevole. Inoltre, dovresti utilizzare un HMAC con il token per evitare manomissioni, anche se stai firmando. In teoria sarebbe ridondante, dal momento che stai firmando con una chiave privata. Tuttavia, HMAC è molto ben testato e la tua implementazione del meccanismo di firma potrebbe essere difettosa. Per questo motivo è meglio usare HMAC. Sareste sorpresi del fatto che molte implementazioni di sicurezza "roll your own" hanno difetti che li portano a scendere a compromessi.

Suoni molto bene per sicurezza. Mantenere il buon lavoro! Abbiamo bisogno di più sviluppatori attenti alla sicurezza in questo mondo.

EDIT:

Si è considerato sicuro per includere i timestamp/ID utente nel token purché sono criptati con una forte simmetrica chiave segreta (come AES, Blowfish, ecc) che solo il server ha e fintanto che il token include un hash a prova di manomissione come HMAC, che è crittografato con la chiave segreta insieme all'ID utente/timestamp. L'hash garantisce l'integrità e la crittografia garantisce la riservatezza.

Se non si include l'HMAC (o altro hash) nella crittografia, è possibile che gli utenti manomettano il token crittografato e lo decifichino su qualcosa di valido. Ho effettuato un attacco su un server in cui l'ID utente e il timestamp sono stati crittografati e utilizzati come token senza hash. Cambiando un carattere casuale nella stringa, sono stato in grado di cambiare il mio ID utente da qualcosa come 58762 a 58531. Mentre non potevo scegliere il "nuovo" ID utente, ero in grado di accedere all'account di qualcun altro (questo era nel mondo accademico , come parte di un corso).

Un'alternativa a ciò consiste nell'utilizzare un valore di token completamente casuale e mapparlo sul lato server all'ID utente registrato/timestamp (che rimane sul lato server e quindi fuori dal controllo client). Ciò richiede un po 'più di memoria e potenza di elaborazione, ma è più sicuro. Questa è una decisione che dovrai prendere caso per caso.

Per quanto riguarda il riutilizzo/derivazione di chiavi dall'IV e da altri tasti, di solito è ok, a condizione che le chiavi siano valide solo per un breve periodo di tempo. Matematicamente è improbabile che qualcuno possa infrangerli. È possibile tuttavia. Se vuoi seguire il percorso paranoico (cosa che faccio di solito), genera tutte le nuove chiavi casualmente.

+0

Grazie per quello. Ho deciso di usare Rijndael e HMAC ma sto ancora cercando di capirlo. Posso usare IV per ricavare la chiave di sessione dalla chiave principale? Posso usare anche la stessa chiave di sessione per l'HMAC o devo ricavare una nuova chiave dalla chiave di sessione corrente? Se ho bisogno di una nuova chiave per HMAC posso usare l'attuale IV per questo o ho bisogno anche di un nuovo valore casuale? Alla fine hai detto che non dovrei crittografare il timestamp con l'ID utente, come posso quindi sapere che il token è scaduto? poiché non riesco a memorizzare un record di sessione nel database. Grazie ancora. –

+0

Grandi domande. Aggiornerò la risposta con alcune informazioni aggiuntive –

+0

Ok, ho capito tutto. Quindi l'HMAC viene calcolato dai dati non crittografati e quindi crittografato con i dati? Devo memorizzare l'HMAC sul server per confrontare in seguito o posso decrittografare il token e quindi calcolare l'HMAC dai dati ora non crittografati e confrontarlo con l'HMAC che è stato crittografato con i dati? –