it-swarm.dev

Perché aggiornare il token CSRF per richiesta modulo?

In molti tutorial e guide vedo che un token CSRF dovrebbe essere aggiornato per richiesta. La mia domanda è: perché devo farlo? Un singolo token CSRF per sessione non è molto più semplice 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 farebbe già un token per sessione. L'unico argomento sembra essere la protezione XSS, ma questo non si applica poiché quando si ha una vulnerabilità XSS lo script potrebbe comunque leggere nuovi token.

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

95
Philipp Gayret

Per i motivi già discussi, non è necessario generare un nuovo token per richiesta. Porta quasi zero vantaggio in termini di sicurezza e ti costa in termini di usabilità: con un solo token valido alla volta, 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 fallirà e probabilmente li saluterà con un messaggio di errore ostile. Se provano ad aprire una risorsa in una seconda scheda, troveranno che la sessione si interrompe in modo casuale in una o entrambe le schede. Di solito non vale la pena menzionare l'usabilità dell'applicazione per soddisfare questo requisito inutile.

C'è è un posto dove vale la pena emettere un nuovo token CSRF, tuttavia: al cambio principale 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: un utente malintenzionato accede al sito e genera una nuova sessione. Prendono l'ID di sessione e lo iniettano nel browser di una vittima (ad es. Scrivendo un cookie da un dominio vicino vulnerabile o utilizzando un'altra vulnerabilità come gli URL jsessionid) e iniettando anche il token CSRF in un modulo nel browser della vittima. Attendono che la vittima acceda con quel modulo, quindi usano un altro post per convincere la vittima a compiere un'azione con il token CSRF ancora attivo.

Per evitare ciò, invalidare il token CSRF ed emetterne uno nuovo nei punti (come il login) in cui si sta già facendo lo stesso per l'ID sessione per impedire attacchi di fissazione della sessione.

111
bobince

Panoramica. Il consiglio standard è di usare un token CSRF unico che è unico per ogni richiesta. Perché? Perché un token per richiesta è un po 'più resistente a determinati tipi di errori di implementazione rispetto a un token per sessione. Ciò rende probabilmente i token per richiesta la scelta migliore per lo sviluppo di nuove applicazioni Web. Inoltre, nessun auditor di sicurezza ti disturberà 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 chiedendoti la logica dettagliata alla base di questo consiglio, o chiedendoti quanto sia grande il rischio se usi un token per sessione, continua a leggere ...


Scavando un po 'più a fondo. La verità è che, se non hai altre vulnerabilità nel tuo sito web, un singolo token CSRF per sessione è OK. Non c'è motivo per cui devi necessariamente avere per generare un nuovo token CSRF per richiesta.

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

Naturalmente, conosco l'argomento per cui alcune persone potrebbero raccomandare di generare un nuovo token CSRF per ogni richiesta. Stanno pensando, se hai anche una vulnerabilità XSS sul tuo sito web, quindi se usi un singolo token CSRF per sessione sarà facile usare XSS per recuperare il token CSRF, mentre se generi un nuovo token CSRF per richiesta, esso richiederà più lavoro per recuperare il token CSRF. Personalmente, non trovo questo argomento estremamente 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 devi affrontare un aggressore serio e competente, è difficile garantire la sicurezza, indipendentemente da come generi i token CSRF.

Nel complesso, non può far male generare un nuovo token CSRF per ogni richiesta. E forse è meglio farlo in questo modo, solo per toglierti gli auditor di sicurezza. Ma se hai già un'applicazione legacy che utilizza un singolo token CSRF per l'intera sessione, spendere i soldi per convertirlo per generare un nuovo token CSRF per ogni richiesta probabilmente non sarebbe altissimo nella mia lista di priorità: scommetto che potrebbe trovare altri usi per quei soldi e l'energia degli sviluppatori che migliorerebbero ancora di più la sicurezza.

23
D.W.

XSS può essere utilizzato 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 accidentalmente clic due volte su Invia. Un buon uso di questo è di impedire all'utente di fare clic su "checkout" due volte e di addebitare accidentalmente il cliente due volte.

Un CAPTCHA o che richiede la password corrente dell'utente può essere utilizzato come misura anti-csrf che non può essere esclusa da XSS.

Consiglio di leggere CSRF Prevention Cheat Sheet .

15
rook

Se il token è lo stesso per l'intera sessione, potrebbe essere possibile per un utente malintenzionato perdere un token da una pagina e utilizzarlo per un'azione diversa.

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

L'uso di un token per richiesta anziché di uno di sessione 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'uso di token separati per ogni richiesta rende questo molto più difficile.

6
Polynomial

Oltre alle altre risposte, potrebbe essere saggio aggiornare anche il token se il server è sensibile all' attacco BREACH .

Ciò richiede le tre condizioni seguenti:

  • Essere servito da un server che utilizza la compressione a livello HTTP
  • Riflettere l'input dell'utente nei corpi di risposta HTTP
  • Riflette un segreto (come un token CSRF ) nei corpi di risposta HTTP

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 riceverà ogni volta un token diverso. Ciò significa che l'utente reale non sarà in grado di inviare il modulo in una situazione MITM.

Naturalmente sono necessarie anche le altre due condizioni per essere vere. Probabilmente sarebbe più facile mantenere un token CSRF per sessione e disabilitare la compressione a livello HTTP per tutte le pagine che servono moduli.

3
SilverlightFox

Non è un fatto molto noto, ma il normale confronto di stringhe è vulnerabile agli attacchi di temporizzazione ( come questo . Per farla breve, normali operazioni di confronto di stringhe (== o ===) confronterà due stringhe carattere per carattere da sinistra a destra e restituirà false una volta che hanno incontrato un carattere che non è uguale in una determinata posizione in entrambe le stringhe. Questo dà una minuscola differenza nei tempi che è stato dimostrato di essere rilevabile .

Usando un attacco di cronometraggio per provare ogni possibile personaggio per ogni posizione, è possibile capire quale sia il token reale. Creando un nuovo token ogni volta che viene inoltrata 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 , che potrebbe essere indesiderabile. Pertanto, è meglio risolvere questo problema utilizzando una funzione di confronto delle stringhe insensibile al tempo come questa .

2
user2428118

Un motivo per voler cambiare il token CSRF per richiesta è mitigare la perdita di compressione del token. Quello che voglio dire è che se l'attaccante Eva può iniettare dati su una pagina contenente il token in cui la pagina viene inviata compressa, Eva può quindi indovinare al primo carattere della stringa che riceve un set di dati più piccolo per la pagina sapendo che ha indovinato, quindi vai al prossimo personaggio.

Questo è simile a un attacco di cronometraggio.

Al momento non vi è alcun motivo (che io conosca) di modificare il token se viene inviato solo nelle intestazioni HTTP.

Un altro metodo consiste nel modificare il token non appena viene rilevata una richiesta non riuscita, ma ciò potrebbe avere problemi con l'utente che non è in grado di inviare alcun modulo.

0
edruid