Come github.com implementa la mitigazione di CSRF

8

Ho esaminato di recente CSRF . La strategia di mitigazione raccomandata è quella di implementare il Pattern token di sincronizzazione .

Quando guardi i dettagli, viene fuori la domanda con quale frequenza questi token devono essere cambiati. Di nuovo, la raccomandazione generale è che i token per sessione sono sufficienti. Puoi richiedere token per richiesta se hai bisogno di ulteriore sicurezza (o se hai uno scenario in cui i gettoni CSRF che perdono è un problema).

Durante la verifica di come i siti di grandi dimensioni implementano la protezione CSRF, ho dato un'occhiata a github.com. Ciò che mi disturba è che non riesco a capire perché hanno implementato il loro approccio come hanno fatto loro.

Mi viene in mente che utilizzano token per richiesta (anche più, unici per token di moduli). Tuttavia, i token precedenti non vengono invalidati dopo che sono stati utilizzati. Darò un esempio.

Consideriamo la pagina dei profili github: link .

La risposta a una richiesta GET contiene tre moduli con un authenticity_token come parametro di input nascosto. Se ricordo male, github è basato su Rails. Quindi questo si adatta, poiché il nome corrisponde al nome predefinito di meccanismo di protezione di Rails CSRF . Inoltre, i token hanno una lunghezza di 64 byte, che corrisponde alla lunghezza del approccio dei token CSRF mascherati di Rails .

I token sono allegati ai seguenti moduli:

  • Token 1: il pulsante Esci
  • Token 2: il pulsante Aggiorna profilo
  • Token 3: il pulsante Salva profilo di lavoro

Se ricarichi la pagina, i valori di tutti e tre i token cambiano.

Consideriamo un POST successivo che aggiorna il mio profilo.

  • Se invio il token previsto 2, l'azione viene eseguita.
  • Se invio un token non valido, l'azione non viene eseguita (il server restituisce HTTP 422).

Fin qui tutto bene, ora alle cose che non capisco. L'azione viene anche eseguita, senza errori, quando faccio una delle seguenti richieste:

  • Invia un altro token dalla pagina (ad esempio Token 1 o Token 3 dall'alto).
  • Invia di nuovo il token 2. Quindi il vecchio token non viene invalidato come utilizzato. Funziona più volte.
  • Ricarica la pagina, ma invia uno dei vecchi token.

Quindi immagino si tratti di: Perché github implementa i token per richiesta (anche per modulo), ma non li invalida mai / verifica che essi appartengano all'elemento modulo corretto?

O forse ho torto completamente, e github implementa effettivamente un approccio diverso (come il modello di token crittografato).

    
posta user32387 19.10.2015 - 18:09
fonte

2 risposte

1

GitHub convalida authenticity_token per implementare una protezione CSRF. Hai ragione che stanno usando un token per modulo.

Tuttavia non sono sicuro che il token non venga mai invalidato. Hai ignorato la possibilità che authenticity_token sia un token a vita breve valido per un periodo di tempo, ad esempio 60 minuti. [Questa cifra non è precisa, verificherò la stessa cosa e aggiornerò la figura esatta qui.]

Ora dalla prospettiva di attacco vediamo quale è il rischio aggiuntivo che un token riutilizzabile possiede su un singolo token CSRF monouso.

Nel momento in cui un token viene convalidato sul lato server per verificare se la richiesta è falsificata, l'applicazione è protetta contro CSRF. Se il token utilizzato non è un token monouso, il possibile vettore di attacco richiede il possesso di almeno un token valido.

Quali sono i modi possibili per ottenere il token anti CSRF valido qui?

L'attaccante dovrà accedere alla memoria del browser per rubare il token che lo rende estremamente difficile e un vettore di attacco quasi impossibile. Inoltre, ricorda che, in GitHub, authenticity_token è valido solo durante una sessione attiva. Nel momento in cui esci e accedi nuovamente, qualsiasi authenticity_token della sessione precedente non sarà più valido.

    
risposta data 26.11.2016 - 14:34
fonte
1

Flusso di lavoro non lineare

La domanda sembra presupporre un flusso di lavoro lineare, ad esempio, l'utente carica la pagina A con token A1; esegue un'azione che richiede quel token; carica nuovamente la pagina A, questa volta con il token A2, ed esegue un'azione che lo richiede.

Tuttavia, è perfettamente ragionevole per gli utenti avere più pagine aperte nella stessa sessione: puoi "usare un token" in una scheda, quindi passare a un'altra scheda che è stata aperta un'ora fa e fare clic su un pulsante che invia un gettone che tecnicamente è molto più vecchio di quello che hai appena usato. Se il token più vecchio sarebbe stato invalidato, sembrerebbe un bug ovvio dal punto di vista dell'utente.

Inoltre, è ragionevole utilizzare il pulsante Indietro, che può tornare a una versione cache della pagina con i token precedenti. È possibile ottenere un modulo con un particolare token, inviare una richiesta POST con questo token, quindi ricordare che è necessario modificare un'altra cosa, premere il pulsante Indietro (che mostra di nuovo il modulo senza recuperare una nuova versione) e quindi inviare un altro POST richiesta con (ovviamente) lo stesso token CSRF che hai appena usato. Ancora una volta, questo è un flusso di lavoro ragionevole, e dovrebbe funzionare, e invalidare il token potrebbe infrangerlo.

Qualche invalidazione dei token CSRF sarebbe ragionevole, ma dovrebbe avvenire in condizioni simili alla scadenza della sessione - sia su un logout esplicito, sia su un timeout relativamente lungo; non semplicemente usando un token più recente, poiché all'interno di una singola sessione è ragionevole che i token vengano usati fuori ordine e / o riutilizzati.

    
risposta data 26.12.2016 - 19:06
fonte

Leggi altre domande sui tag