Token CSRF necessario quando si utilizza l'autenticazione senza stato (= senza sessione)?


125

È necessario utilizzare CSRF Protection quando l'applicazione si basa su un'autenticazione senza stato (utilizzando qualcosa come HMAC)?

Esempio:

  • Abbiamo una pagina singola applicazione (altrimenti dobbiamo aggiungere il segnalino su ogni link: <a href="...?token=xyz">...</a>.

  • L'utente si autentica utilizzando POST /auth. In caso di autenticazione riuscita, il server restituirà un token.

  • Il token verrà memorizzato tramite JavaScript in una variabile all'interno dell'app a pagina singola.

  • Questo token verrà utilizzato per accedere a URL limitati come /admin.

  • Il token verrà sempre trasmesso all'interno delle intestazioni HTTP.

  • NESSUNA sessione HTTP e NESSUN cookie.

Per quanto ho capito, non dovrebbe esserci (?!) alcuna possibilità di utilizzare attacchi cross-site, perché il browser non memorizzerà il token e quindi non può inviarlo automaticamente al server (questo è ciò che accadrebbe quando si utilizzano i cookie / Sessione).

Mi sto perdendo qualcosa?


6
Fai attenzione all'autenticazione di base. Molti browser invieranno automaticamente le intestazioni di autenticazione di base per il resto della sessione. Ciò può rendere l'autenticazione di base vulnerabile a CSRF come l'autenticazione del cookie.
phylae

Risposte:


159

Ho trovato alcune informazioni su CSRF + che non utilizzano cookie per l'autenticazione:

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    "poiché non ti affidi ai cookie, non è necessario proteggerti dalle richieste cross-site"

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    "Se seguiamo il metodo dei cookie, devi davvero fare CSRF per evitare richieste tra siti. Questo è qualcosa che possiamo dimentica quando usi JWT come vedrai. "
    (JWT = Json Web Token, un'autenticazione basata su token per app stateless)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    "Il modo più semplice per eseguire l'autenticazione senza rischiare le vulnerabilità CSRF è semplicemente evitare di utilizzare i cookie per identificare l'utente "

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    "Il problema più grande con CSRF è che i cookie non forniscono assolutamente alcuna difesa contro questo tipo di attacco. Se stai utilizzando l'autenticazione dei cookie devi anche adottare misure aggiuntive per proteggerti dalla CSRF. La precauzione più semplice che puoi adottare è assicurarti che la tua applicazione non compia mai effetti collaterali in risposta alle richieste GET. "

Ci sono molte altre pagine che affermano che non è necessaria alcuna protezione CSRF, se non si utilizzano i cookie per l'autenticazione. Ovviamente puoi ancora usare i cookie per tutto il resto, ma evita di memorizzare qualcosa di simile session_idal suo interno.


Se devi ricordare l'utente, ci sono 2 opzioni:

  1. localStorage: Un archivio di valori-chiave nel browser. I dati memorizzati saranno disponibili anche dopo che l'utente chiude la finestra del browser. I dati non sono accessibili da altri siti web, perché ogni sito ha il proprio archivio.

  2. sessionStorage: Anche un archivio dati nel browser. La differenza è: i dati vengono cancellati quando l'utente chiude la finestra del browser. Ma è comunque utile, se la tua webapp è composta da più pagine. Quindi puoi fare quanto segue:

    • L'utente accede, quindi memorizzi il token sessionStorage
    • L'utente fa clic su un collegamento, che carica una nuova pagina (= un collegamento reale e nessuna sostituzione del contenuto javascript)
    • Puoi ancora accedere al token da sessionStorage
    • Per disconnettersi, è possibile eliminare manualmente il token sessionStorageo attendere che l'utente chiuda la finestra del browser, che cancellerà tutti i dati memorizzati.

(per entrambi dai un'occhiata qui: http://www.w3schools.com/html/html5_webstorage.asp )


Esistono standard ufficiali per l'autenticazione dei token?

JWT (Json Web Token): Penso che sia ancora una bozza, ma è già utilizzata da molte persone e il concetto sembra semplice e sicuro. (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
Sono disponibili anche librerie per molti framework. Basta cercarlo su google!


37
Ottimo riassunto su CSRF! Noterò che l'archiviazione dei token in localStorage o sessionStorage è vulnerabile agli attacchi XSS e che i dati possono essere visualizzati dagli script sulla pagina, quindi se si dispone di uno script compromesso servito da un CDN o se è presente codice dannoso in uno dei Librerie JS, possono rubare il token da quei luoghi di archiviazione. Vedi: stormpath.com/blog/… Penso che l'approccio più sicuro sia memorizzare un token JWT + CSRF nel cookie, quindi posizionare il tuo JWT calcolato con il token CSRF al suo interno nell'intestazione della richiesta.
Aaron Gray,

Riguardo a: "La precauzione più elementare che puoi prendere è assicurarti che la tua applicazione non esegua mai effetti collaterali in risposta alle richieste GET." È possibile che un attacco CSRF simuli una richiesta POST?
Costa

A seconda dell'applicazione lato server, può essere possibile. Esistono Web Frameworks che usano qualcosa di simile http://.../someRestResource?method=POST. Quindi è fondamentalmente una GETrichiesta, ma l'applicazione server la interpreta come una POSTrichiesta, perché è stata configurata per utilizzare il methodparametro anziché l'intestazione HTTP. ...Per quanto riguarda i browser Web comuni, applicano la stessa politica di origine ed eseguiranno solo GETrichieste a server esterni. Anche se potrebbe essere possibile eseguire POSTrichieste se il browser web non applica quegli standard web (bug, malware).
Benjamin M

1
Oltre a Server Side App: Non è ancora possibile inviare un corpo di richiesta, perché i browser comuni non lo consentono. Tuttavia, se l'app server lo consente method=POST, potrebbe anche consentire body={someJson}di sovrascrivere il corpo della richiesta predefinito. Questo è un design API davvero pessimo ed estremamente rischioso. http://...?method=POST&body={someJson}Tuttavia, se la tua app server lo consente , dovresti davvero pensare troppo a cosa hai fatto lì e perché e se è necessario. (Direi che nel 99,9999% dei casi non è necessario). Inoltre i browser possono inviare solo pochi kilobyte in questo modo.
Benjamin M

@BenjaminM nota che la stessa politica di origine impedisce solo al codice javaScript di accedere al risultato, quindi mentre la richiesta è "bloccata" raggiunge effettivamente il server - jsbin.com/mewaxikuqo/edit?html,js,output L' ho testato solo su Firefox, ma puoi aprire strumenti di sviluppo e vedere che anche se ottieni "Cross-Origin Request Blocked", il server remoto in realtà vede l'intera richiesta. ecco perché devi avere token o intestazioni personalizzate (e se possibile entrambi) per tutte le tue richieste POST
Yoni Jah

59

TL; DR

Un JWT, se utilizzato senza cookie, nega la necessità di un token CSRF, MA! memorizzando JWT in session / localStorage, esponi il tuo JWT e l'identità dell'utente se il tuo sito ha una vulnerabilità XSS (abbastanza comune). È meglio aggiungere una csrfTokenchiave al JWT e memorizzare il JWT in un cookie con securee http-onlyattributi impostati.

Leggi questo articolo con una buona descrizione per maggiori informazioni https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

È possibile rendere stateless questa protezione CSRF includendo un'attestazione JWT xsrfToken:

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "tom@andromeda.com", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

Quindi sarà necessario memorizzare csrfToken in localStorage / sessionStorage e nello stesso JWT (che è memorizzato in un cookie sicuro e solo http). Quindi, per la protezione csrf, verificare che il token csrf nel JWT corrisponda all'intestazione del token csrf inviato.


2
Si dovrebbe esentare l'utilizzo del token csrf durante l'autenticazione api dell'utente?
user805981

3
Vale la pena sottolineare (come altri hanno anche menzionato nei commenti sul collegamento sorgente) che qualsiasi mitigazione CSRF che utilizza a) cookie, che non sono solo http o b) memorizza il token CSRF nella memoria locale è vulnerabile a XSS. Ciò significa che l'approccio presentato può aiutare a mantenere segreto il JWT da un utente malintenzionato che utilizza XSS, ma un utente malintenzionato sarebbe comunque in grado di eseguire una richiesta dannosa sulla tua API perché è in grado di fornire un JWT valido (tramite il cookie, grazie browser) e token CSRF (letto tramite JS iniettato dalla memoria / cookie locale).
Johannes Rudolph,

1
In realtà anche un token CSRF non può proteggerti a questo livello di XSS, dal momento che stai assumendo che l'attaccante possa accedere a localStorage, che l'unico modo per accedere attualmente è quello di avere accesso a livello di script, che può comunque dare un'occhiata al token CSRF .
valido il

1
Non è quello che stava dicendo @JohannesRudolph? Non appena memorizzi il token CSRF in Web Storage / cookie non solo http, aumenti la tua impronta di un attacco XSS perché questi sono accessibili tramite JS.
adam-beck

1
Non sono un esperto totale qui, ma se sei ancora esposto a XSS come eri all'inizio, non sono sicuro che la parte sia meglio aggiungere ... vale davvero. Probabilmente è un po 'più complicato per un attaccante ottenere un token CSRF, ma alla fine è comunque in grado di eseguire una richiesta per tuo conto, anche senza conoscere effettivamente il token JWT. È corretto? Grazie
superjos
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.