Domanda:
Perché aggiornare il token CSRF per richiesta di modulo?
Philipp Gayret
2012-10-20 16:15:45 UTC
view on stackexchange narkive permalink

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 quello che un il token per sessione funzionerebbe già. L'unico argomento sembra essere la protezione XSS, ma questo non si applica in quanto quando si ha una vulnerabilità XSS lo script potrebbe leggere comunque nuovi token.

Quali sono i vantaggi di generare nuovi token per richiesta?

Otto risposte:
bobince
2012-10-22 01:31:40 UTC
view on stackexchange narkive permalink

Per i motivi già discussi, non è necessario generare un nuovo token per richiesta. Porta un vantaggio di sicurezza quasi nullo 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 casualmente in una o entrambe le schede. Di solito non vale la pena menomare l'usabilità della tua applicazione per soddisfare questo requisito inutile.

C'è un posto in cui vale la pena emettere un nuovo token CSRF, però: su principal-change inside una sessione. Cioè, principalmente, all'accesso. Questo serve per evitare che un attacco di riparazione della sessione porti a una possibilità di attacco CSRF.

Ad esempio: l'attaccante accede al sito e genera una nuova sessione. Prendono l'ID di sessione e lo iniettano nel browser della vittima (ad es. Scrivendo un cookie da un dominio vicino vulnerabile o utilizzando un'altra vulnerabilità come gli URL jsessionid) e iniettano anche il token CSRF in un modulo nel browser della vittima. Attendono che la vittima acceda con quel modulo, quindi utilizza un altro post del modulo per convincere la vittima a eseguire un'azione con il token CSRF ancora attivo.

Per evitare ciò, invalida il token CSRF e emettine uno nuovo nei punti (come login) in cui stai già facendo lo stesso con l'ID di sessione per prevenire attacchi di riparazione della sessione.

Questo consiglio è ancora valido ora che gli attacchi BREACH sono una cosa?
Gli attacchi BREACH dovrebbero essere risolti a un livello diverso (disabilitando la compressione dei dati dell'applicazione E la compressione TLS), quindi la risposta è: non dovresti preoccuparti dell'attacco BREACH a meno che tu non stia configurando TLS o il server HTTP
D.W.
2012-10-21 04:55:57 UTC
view on stackexchange narkive permalink

Panoramica. Il consiglio standard è di utilizzare un token CSRF univoco che sia univoco per ogni richiesta. Perché? Perché un token per richiesta è leggermente più resistente a determinati tipi di errori di implementazione rispetto a un token per sessione. Ciò rende i token per richiesta probabilmente la scelta migliore per lo sviluppo di nuove applicazioni web. Inoltre, nessun revisore della sicurezza ti darà fastidio 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 e ti chiedi quale sia la logica dettagliata alla base di questo consiglio, o se ti stai chiedendo 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 generare un nuovo token CSRF per richiesta.

Ciò è dimostrato dal fatto che troverai anche rispettabili esperti di sicurezza che affermano che un altro ragionevole Un modo per difendersi da CSRF è utilizzare il doppio invio dei cookie: in altre parole, si utilizza un Javascript lato client che calcola un hash del cookie di sessione e lo aggiunge a ogni richiesta POST, trattando l'hash come il 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 hai anche una vulnerabilità XSS sul tuo sito web, 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, richiederà più lavoro per recuperare il token CSRF. Personalmente, non trovo questo un argomento estremamente convincente. Se hai una vulnerabilità XSS sul tuo sito, è comunque possibile recuperare i token CSRF anche se generi un nuovo token CSRF per ogni richiesta, bastano poche righe in più di Javascript dannoso. In ogni caso, se hai una vulnerabilità XSS sul tuo sito e affronti un aggressore serio e informato, è difficile garantire la sicurezza, indipendentemente da come generi i token CSRF.

Nel complesso, non può far male per generare un nuovo token CSRF per ogni richiesta. E forse è meglio farlo in questo modo, solo per toglierti di dosso i revisori della 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 molto alto nella mia lista di priorità: scommetto che io potrebbe trovare altri usi per quei soldi e l'energia degli sviluppatori che migliorerebbero ulteriormente la sicurezza.

Non li chiamerei "esperti di sicurezza rispettabili" se raccomandassero la doppia sottomissione dei cookie ... XSS non è l'unico problema a portata di mano per questo. OWASP ha una buona carrellata su questo ...
I cookie a doppio invio di @AviD, vanno benissimo. Non ho ancora visto alcuna prova che questo approccio sia sostanzialmente più vulnerabile di qualsiasi altro approccio. Ogni tecnica ha le sue vulnerabilità. Questo non è diverso.
@Gili il problema con i cookie a doppio invio è che questo in genere si riferisce al normale cookie di sessione già esistente - e questo non dovrebbe essere accessibile a JavaScript (ad esempio utilizzando il flag `HttpOnly`). L'utilizzo di questa tecnica può impedire l'attacco CSRF, ma aprirebbe il cookie di sessione ad altri problemi, come renderlo più vulnerabile a possibili vulnerabilità XSS. Esistono tecniche che funzionano bene, senza causare altre vulnerabilità separate.
@AviD, come menzionato in http://security.stackexchange.com/q/61110/5002 OWASP indica agli sviluppatori di utilizzare un cookie separato per il token CSRF proprio per questo motivo. Puoi mantenere il flag `HttpOnly` sul cookie di sessione.
@Gili sì, questo è esattamente il punto.
@AviD, scusa non capisco il tuo punto. Hai detto che i cookie a doppio invio ti costringono a rimuovere il flag "HttpOnly" dal cookie di sessione, ma ho appena spiegato che non è così (puoi utilizzare un cookie separato per il token di doppio invio dei cookie). Questo non invalida il tuo reclamo originale?
@Gili, ha riletto i commenti di AviD. Non perdere il suo uso della parola "tipicamente". L'invio di un doppio cookie è generalmente inteso come il riutilizzo del cookie di sessione. Se qualcuno consiglia l'invio di un doppio cookie e non dispone di alcune dichiarazioni di non responsabilità esplicite contrarie, significa che consiglia di riutilizzare il cookie di sessione. Penso che AviD abbia coperto questo con i suoi commenti sopra.
Giusto. PS: in una nota correlata, http://security.stackexchange.com/a/43550/5002 mette in dubbio il valore di "HttpOnly" contro gli attacchi XSS.
@Gili, sì, lo so. :-) Ho appena pubblicato una risposta alla domanda a cui ti sei collegato e anche collegato alla stessa discussione su `HttpOnly`. Grazie per il puntatore e la discussione!
@Gili sì, esattamente come D.W. disse, quella era esattamente la mia intenzione.
@AviD, Sono contento che siamo entrambi sulla stessa pagina. Grazie per il chiarimento.
"non può far male generare un nuovo token CSRF per ogni richiesta", danneggia l'usabilità (?)
Il token CSRF per ogni richiesta può essere aggiornato, ma devi occuparti delle chiamate Ajax.In un certo senso è un processo noioso, ma la chiamata Ajax può essere aggiornata.
rook
2012-10-20 23:24:34 UTC
view on stackexchange narkive permalink

XSS può essere utilizzato per leggere un token CSRF, anche se è un singolo token di invio, questo è 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 desideri impedire all'utente di fare clic accidentalmente su Invia due volte. Un buon uso di questo è impedire che l'utente faccia clic due volte su "checkout" e addebiti accidentalmente il cliente due volte.

Un CAPTCHA o la richiesta della password corrente dell'utente può essere utilizzato come misura anti-csrf essere bypassato da XSS.

Consiglio di leggere il CSRF Prevention Cheat Sheet.

Non vedo come un CAPTCHA o l'inserimento della password sarebbero sicuri di fronte a XSS. Forza solo l'attaccante a saltare alcuni cerchi aggiuntivi.
@CodesInChaos l'attaccante dovrebbe conoscere la password, e quindi è un punto controverso.
Se l'utente inserisce la password a un certo punto dopo l'xss, l'attaccante può probabilmente rubarla. Quindi reinserire la password aiuta un po ', ma non molto.
@CodesInChaos Funziona bene sulla carta, ma è molto meno probabile che questo attacco proposto abbia successo in uno scenario reale.
@CodesInChaos hai ragione sul fatto che un CAPTCHA sarebbe irrilevante per questo. D'altra parte, la riautenticazione (selettivamente su azioni sensibili) è una delle migliori soluzioni per CSRF e dovrebbe essere utilizzata di più. Vedere anche la discussione di Schneier sull '"autenticazione della transazione", che è simile, sebbene non identica.
I token monouso hanno ancora più vantaggi (almeno per le operazioni mission-critical): aggiungono sicurezza contro [replay attack] (http://en.wikipedia.org/wiki/Replay_attack).
@Domi Dipende da come hanno ottenuto il token in primo luogo. Se fosse con XSS, o su un canale non sicuro, il token rotolante non avrebbe importanza.
Aggiungono ancora sicurezza contro gli attacchi di replay, dato che non c'è XSS.
Polynomial
2012-10-20 18:37:03 UTC
view on stackexchange narkive permalink

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

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

Usare un token per richiesta invece di uno a livello 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ò prendere di mira qualsiasi pagina per rubare il token. L'utilizzo di token separati per ogni richiesta rende tutto più difficile.

Non c'è modo che qualcuno possa estrarre qualcosa da iframe, questo violerebbe la [stessa politica di origine] (http://en.wikipedia.org/wiki/Same_origin_policy)
@SkPhilipp Scusa, volevo dire tramite XSS.
Utilizzando un XSS dovrebbe essere possibile estrarre il token anche se aggiornato ad ogni richiesta. Ho ragione?
Sì, tramite XSS potresti quindi caricare un iframe in un modulo di modifica della password e potresti estrarre quel token, la generazione di nuovi token non lo renderebbe sicuro se hai una vulnerabilità XSS.
-1 Mi dispiace ma non voglio che le persone abbiano l'idea che se usano un singolo token di invio sono magicamente protetti da XSS, perché questo è molto falso. Se un utente può farlo in un browser web, allora xss può farlo in un browser web.
@Rook Eh? Non ho mai detto che usare un singolo token fosse buono ...
Se hai una vulnerabilità XSS puoi utilizzare un XHR per leggere qualsiasi pagina e inviare qualsiasi richiesta. Avere un token diverso su ogni pagina non aiuta.
@Rook Non sto dicendo che risolva completamente il problema, ma lo rende più difficile se usi token individuali e li blocchi a richieste specifiche. Posso capire perché sei preoccupato che la risposta dia un'impressione sbagliata, però.
SilverlightFox
2015-11-30 16:45:14 UTC
view on stackexchange narkive permalink

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

Ciò richiede le seguenti tre condizioni:

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

Per mitigare BREACH dovresti 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 hai bisogno che anche le altre due condizioni siano 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.

user2428118
2015-07-17 15:45:15 UTC
view on stackexchange narkive permalink

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 === ) confronteranno due stringhe carattere per carattere da sinistra a destra e restituiranno false una volta che hanno incontrato un carattere che non è uguale in una determinata posizione in entrambe le stringhe. Questo dà una minuscola differenza di tempistica che è stata dimostrata essere rilevabile.

Utilizzando un attacco a tempo per provare ogni possibile personaggio per ogni posizione, è possibile capire quale sia il gettone effettivo. Creando un nuovo token ogni volta che viene inviata una richiesta con un token, questo attacco può essere prevenuto.

Naturalmente, questo funziona solo se si ricrea anche il token se un non valido è stato inviato il token, il che potrebbe non essere desiderabile. Pertanto, è meglio risolvere questo problema utilizzando una funzione di confronto delle stringhe insensibile al tempo come questa.

Va bene, ma devo notare negli esempi e nel documento che hai elencato un attaccante teorico potrebbe misurare il tempo di clock della CPU in modo molto preciso. La macchina non era sottoposta a nessun altro carico e molte lingue utilizzano codici hash precalcolati per il confronto delle stringhe prima di eseguire un controllo carattere per carattere.
I confronti di tempo costante possono e devono essere usati per mitigare questo problema (loop su tutti i caratteri e xor un flag di differenza).
edruid
2015-04-23 20:30:37 UTC
view on stackexchange narkive permalink

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

Questo è simile a un attacco a tempo.

Al momento non c'è motivo (che io sappia) per cambiare 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.

Bhuvanesh
2015-07-17 12:37:51 UTC
view on stackexchange narkive permalink

Se lo stesso token viene utilizzato per l'intera sessione, è probabile che l'autore dell'attacco possa dirottare il token utilizzando XSS e utilizzare la sessione della vittima per svolgere alcune attività dannose come cambiare la password .

Possono modificare le password inserendo un iframe nel sito che stai utilizzando.

Quindi è meglio utilizzare un token per richiesta per evitare che l'attaccante ottenga l'accesso a quel token.

Un utente malintenzionato che utilizza XSS può ottenere l'accesso a nuovi token, questo è ciò di cui tratta l'intera domanda. Vedi anche i commenti su http://security.stackexchange.com/a/22904/15195


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...