Protezione di una API REST a livello di messaggio

11

Vorrei un feedback sulla seguente idea di autenticazione, ha senso e c'è uno standard modo di fare questo (o simili) così posso fare affidamento su un'implementazione ben testata.

Ho visto molte risposte qui su come proteggere la comunicazione con il server, e la maggior parte delle risposte sono semplicemente usa TLS correttamente. Sto cercando una soluzione che consenta la crittografia e la firma dei messaggi stessi, quindi il messaggio rimane al sicuro mentre attraversano il back-end, fino a quando raggiungono il servizio di destinazione.

Contesto

  • App per dispositivi mobili per Android 2.3+ e iOS 6+ creati con phonegap (quindi le librerie usate dovrebbero essere utilizzabili da Java / obj-c o js)
  • L'app comunica con il server utilizzando un REST json api
  • Il contenuto del messaggio deve rimanere confidenziale mentre attraversa il back-end (nessuna terminazione su proxy / bilanciamento del carico)
  • Dovrebbe supportare "ricordami", quindi l'utente non deve inserire nuovamente la passphrase per tutto il tempo
  • Tutte le comunicazioni sono fatte su ssl / tls

Autenticazione

  • il client raccoglie le credenziali dell'utente (nome utente, passphrase e alcune informazioni di sicurezza aggiuntive)
  • il client genera una chiave simmetrica
  • il client crittografa le credenziali con la chiave simmetrica
  • il client crittografa la chiave simmetrica con la chiave pubblica del server (fornita con il client)
  • il client invia il messaggio crittografato, chiave e nonce tramite https (convalida del certificato del server)
  • il proxy server inoltra la richiesta di autenticazione al servizio di autenticazione
  • il servizio di autenticazione decrittografa la chiave simmetrica e il messaggio
  • se le credenziali sono valide, il servizio genera un token di autenticazione
  • il token è associato alla chiave simmetrica sul server, se le credenziali non sono valide, la chiave viene scartata dopo aver risposto alla richiesta
  • il token viene restituito all'utente, crittografato con la chiave simmetrica
  • il token e la chiave sono memorizzati localmente sul client, crittografati da una breve password

Suppongo che queste richieste siano al riparo dagli attacchi di ripetizione se si utilizza tls, quindi non c'è il rischio che un utente malintenzionato riesegua il messaggio per ottenere un nuovo token.

Altre chiamate API

  • il client genera i messaggi di richiesta, lo crittografa e firma il messaggio crittografato
  • il client invia il messaggio crittografato, nonce e firma con il suo token di autenticazione al server
  • alla ricezione il server cerca la chiave associata al token ricevuto, verifica la firma e decrittografa il messaggio prima di elaborarlo

Domande

  • c'è qualche problema con il riutilizzo della stessa chiave simmetrica?
  • qual è una buona scelta di chiave simmetrica?
    • Che dire di AES-OCB o AES-CBC + firma HMAC?
  • quanto spesso dovrebbe essere cambiata la chiave simmetrica?
  • Qual è il modo migliore di aggiornare la chiave / i token di aggiornamento? Stavo pensando di emettere un token di aggiornamento durante la risposta di autenticazione e le chiavi scadono dopo un periodo specifico, quindi se l'utente non aggiorna le proprie chiave devono accedere nuovamente.

Grazie

    
posta Nicolas Esteves 16.06.2013 - 22:05
fonte

2 risposte

5

A meno che non mi sia sfuggito qualcosa, la tua soluzione sembra terribilmente simile a un servizio token di sicurezza. Per un STS, la chiave è avere una parte affidabile per identificare la parte che avvia la parte relying. Nel tuo caso il trust broker e il relying party sembrano essere la stessa entità.

Se il tuo obiettivo è far propagare la fiducia alla destinazione finale, usa semplicemente SSL attraverso il proxy e usa un certificato client per identificare il punto finale. Supponendo che tu voglia che HTTP passi attraverso il tuo proxy per ispezionare il traffico, implementa un STS standard.

Come ha detto Xander, REST è ottimo per le chiamate di servizio leggere, ma nel momento in cui vuoi fare sicurezza dovresti usare SOAP, in particolare l'estensione WS-Security. Non è così difficile, specialmente se controlli entrambe le estremità come fai tu. Vedi questo domanda di overflow dello stack per come farlo in Java su Android.

Se vai avanti con la soluzione a casa, vale la pena notare che gli ultimi tre proiettili nella tua Autenticazione sembrano essere il tuo punto debole.

    
risposta data 17.06.2013 - 11:02
fonte
2

Non posso dire di averli esaminati nei dettagli, ma potresti essere interessato ai tentativi esistenti di implementare Message-Level Security a livello HTTP. Ad esempio:

Entrambi i progetti sembrano inattivi. Possono anche mancare il controllo esperto che altri protocolli di sicurezza solitamente hanno o dovrebbero avere. Questo non vuol dire che ci sia qualcosa di sbagliato in loro. Sospetto che la mancanza di successo di HTTPsec sia dovuta piuttosto al suo arrivo durante le "guerre SOAP vs REST" (aggiungendo un po 'di complessità sul lato REST) e il fatto che avesse solo un'implementazione (in Java) con un non- licenza gratuita.

Indagare se la crittografia e la firma delle entità dei messaggi con strumenti esistenti come OpenPGP potrebbero essere di interesse.

REST è una parola che ha un significato diverso per varie persone. A volte, significa solo payload su HTTP, senza i molteplici livelli di SOAP. Se tali servizi effettivamente seguono i principi HATEOS è un'altra questione.

La mia opinione personale su questo è che l'apolidia di REST dovrebbe essere applicata alle caratteristiche principali dell'applicazione, non necessariamente ai suoi aspetti di sicurezza. Ovviamente è molto difficile (se non impossibile) impedire attacchi di riproduzione senza mantenere una sorta di stato sul lato del destinatario.

Detto questo, non sono sicuro dalle tue domande che sei interessato alla pura sicurezza a livello di messaggio. Piuttosto, sembra che tu sia interessato principalmente al tunneling di un equivalente di SSL / TLS tramite HTTP, perché non sei in grado di eseguire una connessione TCP diretta dal client al back-end. Poiché stai anche utilizzando SSL / TLS, questo suggerisce che il motivo principale di tutto questo è che non ti fidi del bilanciamento del carico. Cercare di scrivere il proprio protocollo è generalmente difficile, e spesso una cattiva idea. Le raccomandazioni riguardanti la crittografia e gli algoritmi MAC dipendono dai dettagli. (In confronto, ci sono voluti alcuni istanti per identificare e affrontare alcuni problemi con TLS, anche se si tratta di un protocollo aperto con specifiche dettagliate, studiato da un numero di esperti.)

    
risposta data 17.06.2013 - 16:23
fonte

Leggi altre domande sui tag