Perché aggiornare il token CSRF per richiesta di modulo?

85

In molti tutorial e guide vedo che un token CSRF deve essere aggiornato per ogni richiesta. La mia domanda è: perché devo farlo? Non è un singolo token CSRF per sessione molto più facile che generarne uno per richiesta e tenere traccia di quelli richiesti?

La generazione del token su base per richiesta non sembra migliorare la sicurezza oltre a quella che un token per sessione potrebbe già fare. L'unico argomento sembra essere la protezione XSS, ma questo non si applica in quanto quando si ha una vulnerabilità XSS lo script potrebbe comunque leggere nuovi token.

Quali sono i vantaggi della generazione di nuovi token per richiesta?

    
posta Philipp 20.10.2012 - 13:15
fonte

8 risposte

97

Per i motivi già discussi, non è necessario generare un nuovo token per richiesta. Offre quasi zero vantaggi in termini di sicurezza e ti costa in termini di usabilità: con un solo token valido contemporaneamente, l'utente non sarà in grado di navigare normalmente nella webapp. Ad esempio, se premono il pulsante "Indietro" e inviano il modulo con nuovi valori, l'invio non riuscirà e probabilmente li saluterà con un messaggio di errore ostile. Se tentano di aprire una risorsa in una seconda scheda, scopriranno che la sessione si interrompe in modo casuale in una o entrambe le schede. Di solito non vale la pena mutare l'usabilità della tua applicazione per soddisfare questo inutile requisito.

è un posto dove vale la pena rilasciare un nuovo token CSRF, tuttavia: su principal-change all'interno di una sessione. Questo è, principalmente, al login. Questo serve a prevenire un attacco di fissazione della sessione che porta a una possibilità di attacco CSRF.

Ad esempio: attacker accede al sito e genera una nuova sessione. Raccolgono l'ID di sessione e lo inseriscono nel browser di una vittima (ad es. Scrivendo un cookie da un dominio vulnerabile vicino o utilizzando un'altra vulnerabilità come jsessionid URL) e iniettano anche il token CSRF in un modulo nel browser della vittima. Attendono che la vittima effettui l'accesso con quel modulo e quindi utilizzano un altro post del modulo per consentire alla vittima di eseguire un'azione con il token CSRF ancora in vita.

Per impedire ciò, invalida il token CSRF ed eseguine uno nuovo nei posti (come login) che stai già facendo lo stesso con l'ID di sessione per prevenire attacchi di fissazione della sessione.

    
risposta data 21.10.2012 - 22:31
fonte
19

Panoramica. Il consiglio standard è di utilizzare un token CSRF univoco che è unico per ogni richiesta. Perché? Poiché un token per richiesta è un po 'più resiliente a certi tipi di errori di implementazione rispetto a un token per sessione. Ciò rende i token per-request probabilmente la scelta migliore per lo sviluppo di nuove applicazioni web. Inoltre, nessun revisore della sicurezza ti assilla sull'utilizzo di un token CSRF per richiesta.

Se sei uno sviluppatore di applicazioni web, questo è tutto ciò che devi sapere e puoi smettere di leggere qui. Ma se sei un esperto di sicurezza che si chiede quale sia la logica dettagliata alla base di questo consiglio, o ti chiedi quanto sia grande il rischio se usi un token per sessione, continua a leggere ....

Scava un po 'più in profondità. La verità è che, se non si hanno altre vulnerabilità nel proprio sito Web, un singolo token CSRF per sessione è OK. Non c'è motivo per cui devi avere per generare un nuovo token CSRF per richiesta.

Ciò è dimostrato dal fatto che troverai anche esperti di sicurezza affidabili che sostengono che un altro ragionevole modo per difendersi da CSRF è l'uso della doppia presentazione dei cookie: in altre parole, usi un Javascript sul lato client che calcola un hash del cookie di sessione e lo aggiunge a ciascuna richiesta POST, trattando l'hash come token CSRF. Puoi vedere che questo essenzialmente genera al volo un token CSRF che è lo stesso per l'intera sessione.

Naturalmente, conosco l'argomento per cui alcune persone potrebbero consigliare di generare un nuovo token CSRF per ogni richiesta. Stanno pensando, se si dispone anche di una vulnerabilità XSS sul proprio sito Web, se si utilizza un singolo token CSRF per sessione sarà facile utilizzare XSS per recuperare il token CSRF, mentre se si genera un nuovo token CSRF per richiesta, richiederà più lavoro per recuperare il token CSRF. Personalmente, non trovo questo argomento terribilmente convincente. Se hai una vulnerabilità XSS sul tuo sito, è ancora possibile recuperare i token CSRF anche se generi un nuovo token CSRF per ogni richiesta, bastano poche righe extra di Javascript dannoso. In entrambi i casi, se hai una vulnerabilità XSS sul tuo sito e affronti un aggressore serio e ben informato, è difficile garantire la sicurezza, indipendentemente dal modo in cui generi i token CSRF.

Nel complesso, non può fare male generare un nuovo token CSRF per ogni richiesta. E forse è meglio farlo in quel modo, solo per toglierti i controllori della sicurezza. Ma se hai già un'applicazione legacy che utilizza un singolo token CSRF per l'intera sessione, spendere i soldi per convertirla per generare un nuovo token CSRF per ogni richiesta probabilmente non sarebbe super-alta nella mia lista di priorità: scommetto che potrebbe trovare altri usi per quei soldi e l'energia degli sviluppatori che migliorerebbero ulteriormente la sicurezza.

    
risposta data 21.10.2012 - 01:55
fonte
12

XSS può essere usato per leggere un token CSRF, anche se si tratta di un singolo token di invio, che è un gioco da ragazzi. È probabile che questa raccomandazione di un singolo token di invio provenga da qualcuno che non comprende CSRF.

L'unico motivo per utilizzare un "token di invio singolo" è se si desidera impedire all'utente di fare clic per inviare due volte per errore. Un buon uso di ciò è impedire all'utente di fare clic su "checkout" due volte e caricare accidentalmente il cliente due volte.

Un CAPTCHA o la richiesta della password corrente dell'utente possono essere utilizzati come misura anti-CSRF che non può essere bypassata da XSS.

Raccomando di leggere il foglio Cheat di prevenzione CSRF .

    
risposta data 20.10.2012 - 20:24
fonte
6

Se il token è uguale nell'intera sessione, è possibile che un utente malintenzionato perda un token da una pagina e lo usi per un'azione diversa.

Ad esempio, è possibile utilizzare un iframe per caricare una pagina, quindi estrarre il token utilizzando una vulnerabilità XSS. Da lì, puoi utilizzare quel token per inviare un modulo di modifica della password

L'uso di un token per richiesta invece di uno a livello di sessione lo rende più difficile, ma non impedisce CSRF. Un utente malintenzionato può semplicemente sfruttare un XSS per leggere il token dalla pagina, quindi attivarlo. Tuttavia, se il token è globale anziché limitato a quella singola pagina, un utente malintenzionato può scegliere come target qualsiasi pagina per rubare il token. L'utilizzo di token separati per ogni richiesta rende molto più difficile.

    
risposta data 20.10.2012 - 15:37
fonte
3

Oltre alle altre risposte, potrebbe essere consigliabile aggiornare anche il token se il tuo server è soggetto a attacco BREACH .

Ciò richiede le seguenti tre condizioni:

  • Be served from a server that uses HTTP-level compression
  • Reflect user-input in HTTP response bodies
  • Reflect a secret (such as a CSRF token) in HTTP response bodies

Per mitigare BREACH è necessario aggiornare il token CSRF sulla richiesta GET che carica un modulo per invalidare tutti i token precedenti. In questo modo, un MITM (Man-In-The-Middle) che crea richieste aggiuntive per scoprire il token nella pagina otterrà ogni volta un token diverso. Ciò significa che l'utente reale non sarà in grado di inviare il modulo in una situazione MITM.

Naturalmente hai bisogno che anche le altre due condizioni siano valide. Probabilmente sarebbe più semplice mantenere un token CSRF per sessione e disabilitare la compressione a livello HTTP per qualsiasi pagina che serva i moduli.

    
risposta data 30.11.2015 - 11:45
fonte
1

Non è un fatto molto noto, ma il confronto tra stringhe normali è vulnerabile agli attacchi temporali ( come questo == o === ) confronteranno due stringhe carattere per carattere da sinistra a destra e restituiranno false una volta che hanno incontrato caratteri non uguali in una data posizione in entrambi stringhe. Ciò fornisce una minuscola differenza di tempistica che è stata rilevabile per essere rilevabile .

Usando un attacco di cronometraggio per provare tutti i possibili caratteri per ogni posizione, è possibile capire quale sia il vero token. Creando un nuovo token ogni volta che viene inviata una richiesta con un token, questo attacco può essere prevenuto.

Ovviamente, questo funziona solo se si ricrea anche il token se è stato inviato un token non valido , il che potrebbe non essere desiderabile. Pertanto, è meglio sistemarlo utilizzando una funzione di confronto tra stringhe non sensibili al tempo come questa .

    
risposta data 17.07.2015 - 12:45
fonte
0

Un motivo per cui si desidera modificare il token CSRF per richiesta è di attenuare la perdita di compressione del token. Ciò che intendo è che se l'attaccante Eve può iniettare dati su una pagina contenente il token in cui la pagina viene inviata Eva compressa può quindi indovinare il primo carattere della stringa che riceve un set di dati più piccolo per la pagina sapendo che ha indovinato, quindi andare sul prossimo personaggio.

Questo è simile a un attacco di temporizzazione.

Al momento non c'è alcun motivo (che io sappia) per cambiare il token se viene inviato solo nelle intestazioni HTTP.

Un altro metodo è quello di cambiare il token non appena viene scoperta una richiesta non riuscita, ma questo potrebbe avere problemi con l'utente che non è in grado di inviare alcun modulo.

    
risposta data 23.04.2015 - 17:30
fonte
-1

Se lo stesso token viene utilizzato per l'intera sessione, allora c'è una probabilità che l'attaccante possa dirottare il token usando XSS e utilizzare la sessione della vittima per svolgere attività dannose come cambiare la password .

Possono fondere le password loda un iframe nel sito che stai utilizzando.

Quindi è meglio usare un token per richiesta per evitare che l'attaccante acceda a quel token.

    
risposta data 17.07.2015 - 09:37
fonte

Leggi altre domande sui tag