Protezione contro CSRF, JWT, cross domain

0

Ho un'app di frontend pesante con una pausa API in node.js. L'app e il back-end sono su host diversi. Inoltre, è possibile accedere all'app sia con http che con https. Il motivo per cui il contenuto è misto: gli utenti dell'applicazione caricano i propri siti Web negli iframe e, se un sito Web è http, non funzionerà, spezzato https rosso al meglio, non caricando affatto nel peggiore dei casi. Abbastanza ironico sul fatto che qualcosa che dovrebbe migliorare la sicurezza del web, mi costringe a consentire l'utilizzo di connessioni non sicure. Ma non è questo il punto. Diciamo che ho il mio frontend su http (s): //app.mydomain.com e backend al link

E voglio renderlo il più sicuro possibile, considerando che i miei utenti a volte usano connessioni non sicure. So che non posso proteggere da manomissioni, ma almeno posso proteggere il token di autenticazione. Quindi io uso JWT. Voglio anche ricordarmi di funzionalità. localStorage / sessionStorage consentirebbe di leggere il token su pagine http non sicure, quindi stavo pensando di impostare un cookie per link sul server. In questo modo, il frontend non può mai leggere il token a causa di CORS. E salterò tutte queste cose con i token di aggiornamento. Ci sarebbe solo un gettone da utilizzare per tutto. Quindi, se un utente ha effettuato l'accesso, il server imposterà il token cookie e lo imposterà alla scadenza al termine della sessione del browser, il token stesso verrà impostato per scadere entro 1 giorno. Se l'utente ha selezionato Ricordami, il cookie verrà impostato per un anno e il token verrà impostato per scadere in un anno. Ora vorrei chiederti se è un modo sicuro per farlo? Sto pensando corretto?

Un'altra cosa ovviamente è CSRF. Stavo pensando solo a controllare il referer e lasciarlo, ma ho sentito che potrebbe bloccare utenti legittimi dietro proxy che rimuovono il referer dalla richiesta. Quindi stavo pensando di usare JWT come nonces. Fondamentalmente su init, quando l'utente si collega / autentica, il server restituisce un nuovo token e quindi il token viene archiviato nella memoria del client e inviato con ogni richiesta al server da verificare.

Ecco un riepilogo del processo:

the frontend is at http(s)://app.mydomain.com
the server is at https://api.mydomain.com

0. make an ajax call to check if the user is logged in
1. send username and password to log in
2. the server sets the cookie at https://api.mydomain.com containing the auth token
    cookie is set to expire when browser session ends, token is set to expire in 1 day
    if remember me: both cookie and token is set to expire in 1 year
3. the server also generates a different token to serve as a nonce and returns it
4. the app stores the nonce token in memory and uses it for every call

If the user is logged in, skip to step 3.

Cosa ne pensi? È sicuro?

    
posta Maciej Krawczyk 28.05.2017 - 13:32
fonte

1 risposta

1

In generale non c'è nulla di sbagliato nella strategia di autenticazione e anti-CSRF delineata. L'implementazione errata di qualsiasi sua parte potrebbe, naturalmente, esporre il rischio, ma la strategia da sola sembra soddisfacente.

Ci sono alcune aree che non sono ideali, la più grande che hai già identificato: supportare l'uso non crittografato di HTTP. Come hai giustamente sottolineato, questo espone un significativo rischio man-in-the-middle. Oltre al rischio intrinseco per i visitatori o gli utenti che scelgono di non utilizzare la comunicazione crittografata con SSL, ma generalmente espone anche maggiori rischi per attacchi di stripping SSL contro gli utenti che intendono utilizzare SSL. Qualcosa che potreste considerare qui sta rendendo disponibile un'opzione solo SSL a livello dell'utente (o dell'organizzazione dell'utente, se appropriato). I dettagli di implementazione dipenderanno dallo stack, ma se stai usando qualcosa come Express o Koa potresti avere un pezzo di middleware che convalida che le richieste HTTP sono permesse prima di restituire una risposta. Nei casi in cui non sono consentiti, puoi rispondere con un reindirizzamento 302 al percorso HTTPS.

I principali vantaggi che posso vedere per l'utilizzo di un cookie rispetto all'archiviazione locale in questo caso sono i seguenti:

  1. Il flag HTTPOnly riduce il rischio di furto di token tramite cross-site scripting (XSS). Questo sicuramente non sarebbe l'unica preoccupazione se si hanno difetti XSS, dal momento che lo sfruttamento di successo potrebbe ancora emettere richieste dalla sessione compromessa.
  2. Se si determina se l'autenticazione viene inizialmente eseguita su SSL (HTTPS), è possibile aggiungere dinamicamente il flag di protezione al cookie quando lo si esegue in modo che lo svernamento SSL esponga un rischio leggermente inferiore poiché il token non verrebbe incluso a lungo l'autenticazione era al sicuro in primo luogo. Esiterei a chiamare questa difesa infallibile contro l'eliminazione di SSL, ma è un modo semplice per aggiungere un po 'di difesa in profondità.
  3. Mi può mancare un modo in cui devo ammettere che non ho quasi mai usato l'API di localstorage, ma penso che avresti bisogno di scope localstorage sull'intero dominio, il che significa che anotherapp.mydomain.com (in linea con il tuo esempio) è vulnerabile, potrebbe compromettere la tua memoria locale contenente il tuo token. Con il cookie, puoi impostarlo su api.mydomain.com e utilizzare anche intestazioni CORS abbastanza restrittive come access-control-allow-origin: app.mydomain.com con access-control-allow-credentials .

Non è chiaro per me se ciò che stai introducendo negli iframe sia destinato in qualche modo a interagire con il tuo contenuto - qualcosa su cui certamente fare attenzione. In un caso ideale, si sarebbe in grado di stipulare che tutti i contenuti incorporati hanno un certificato SSL valido, e basta usare HTTPS in tutto. Senza di questo, semplicemente non avrai abbastanza difese sufficienti per essere ragionevolmente sicuro degli attacchi man-in-the-middle.

    
risposta data 28.05.2017 - 20:18
fonte