Meccanismo di protezione CSRF personalizzato senza token persistenti

0

Ho avuto questa funzionalità (protezione csrf) da un po 'di tempo. La cosa che non mi è mai piaciuta è che ha salvato i token csrf nel file di sessione. Anche se potrebbe non essere un problema reale, lo vedo come un dolore perché alla fine i token potrebbero accumularsi, quindi ho bisogno di utilizzare un meccanismo gc e tenere traccia di ciò che è stato emesso quando e tutto sembra troppo per me.

Quindi ho passato gli ultimi due giorni a migliorare questa "imperfezione" ed ecco cosa ho scoperto. Non pubblicherò alcun codice reale, spiegherò solo l'idea.

Quando viene emesso un modulo, per impostazione predefinita viene generato un token. Il token è costituito da alcuni dati univoci per l'utente, come ID sessione o ID utente, combinati con la stringa datetime corrente in formato YmdHi . Tutto questo è crittografato usando password_hash e ho pensato di offuscare ulteriormente l'hash scambiando parti di esso ma non l'ho ancora fatto.

La convalida è stata un po 'complicata e si è rivelata piuttosto deludente. Per convalidare un token, creo un ciclo che raccoglie le stesse informazioni sull'utente con la data e sottrae 1 minuto per ogni iterazione. Il numero di iterazioni è uguale alla quantità di minuti per cui il token è valido, che non è memorizzato nel token, quindi tutti i token devono essere validi per lo stesso intervallo di tempo, che non mi sembra ancora uno svantaggio.

Voglio chiederti se vedi eventuali difetti e exploit con questo concetto.

L'unico problema possibile è che i token non sono effettivamente conservati dal server, quindi teoricamente chiunque può assemblare un token valido, tuttavia penso che sia altamente improbabile che qualcuno possa passare giorni a raccogliere i token e che capiti di avere un super-computer nel loro seminterrato per eseguire analisti statistici, che non garantisce nuovamente che sarebbero in grado di decifrare la crittografia.

In ogni caso, suppongo che dovrei smettere di esporre la mia incompetenza e lasciare che le persone intelligenti decidano cosa succede.

    
posta php_nub_qq 29.05.2015 - 21:31
fonte

4 risposte

2

Personalmente, non ho mai visto qualcuno approvare la propria alternativa a uno standard di settore per la sicurezza e farlo risultare una soluzione accettabile. Una frase che sento gettare molto nella comunità di sicurezza è "Non rollare la tua".

Leggendo su quello che stai facendo sembra che tu possa essere troppo intelligente per il tuo bene. Sembra una soluzione complessa che potrebbe essere meno sicura della semplice creazione di un token CSRF. Se qualcuno eredita il tuo codice, probabilmente la sua testa esploderà.

Non sono sicuro di dove stia memorizzando il token che stai creando, ma se è in un cookie non c'è alcuna protezione. Se stai posizionando il token in un campo nascosto nel modulo, in sostanza stai utilizzando una versione modificata stranamente di doppia protezione cookie CSRF .

Il mio consiglio: non andare su questa strada. Nel migliore dei casi sarà più complesso e sicuro. Nel peggiore dei casi sarà più complesso e non funzionerà.

    
risposta data 29.05.2015 - 22:15
fonte
1

Penso anche che potresti essere sopra pensiero / ingegneria qui. Mi sembra che la tua combinazione di autorizzazione di sessione con protezione CSRF. Non sono un programmatore PHP, ma in tutti i linguaggi e le strutture che ho usato, questo livello di protezione è disponibile in qualche modo. Probabilmente stai meglio usando una soluzione consolidata piuttosto che la tua.

La maggior parte delle soluzioni che ho visto non generano nuovi token per ogni richiesta, Solitamente, c'è un singolo token per sessione e viene memorizzato con i dati di sessione, quindi non vi è alcun problema relativo al GC. Tutto quello che il token dovrebbe fare è verificare che la risposta provenga dallo stesso client al quale è stato inviato il modulo. Di solito si presume che la sessione sia già autorizzata. Se sei preoccupato per l'autorizzazione della sessione, allora hai comunque maggiori problemi perché l'attaccante potrebbe semplicemente dirottare la sessione, nel qual caso, riceveranno un token 'legittimo' quando richiederanno il modulo.

    
risposta data 30.05.2015 - 02:09
fonte
1

Se vuoi evitare una memoria extra nel database o nella sessione dell'applicazione, perché non usare semplicemente Double Submit Cookies metodo di prevenzione.

Qui semplicemente invii un valore cookie duplicato tramite un altro meccanismo insieme a ciascuna richiesta, ad esempio all'interno di un campo modulo nascosto.

Ad esempio, genera un valore casuale crittograficamente sicuro con 32 bit di entropia. Memorizza questo valore in un cookie denominato csrftoken e in ogni modulo come un campo nascosto denominato csrftoken . Quando ogni modulo viene inviato, controlla che la percentuale dicsrftoken inviata da entrambi i meccanismi di consegna corrisponda.

Non utilizzare ID sessione per questo: la pagina OWASP consiglia di utilizzare un valore separato dall'ID sessione poiché offre una protezione aggiuntiva contro la perdita dell'ID sessione. Proteggi il tuo ID sessione il più possibile e non esponendolo inutilmente contribuirà a mantenere la gestione sicura delle sessioni. Ricorda che non devono memorizzare questo lato del server token aggiuntivo. Tutto quello che stai facendo in termini di funzionalità è controllare che il token POSTed corrisponda al cookie - non ha importanza quale sia il valore per il tuo server. Tutto ciò che importa è che lo stesso valore viene inviato tramite cookie come tramite il modulo, in quanto un utente malintenzionato non conoscerebbe questo valore e pertanto non sarebbe in grado di inviarlo da solo.

Nota che non è necessario un token CSRF separato per modulo. L'unico modo in cui un utente malintenzionato recupera un token passa attraverso un'altra vulnerabilità (come XSS). E se possono eseguire XSS, hanno già sconfitto questo tipo di protezione CSRF. Dovresti comunque rigenerare il token per ogni nuova sessione per impedire qualsiasi tipo di forza bruta persistente contro di essa.

    
risposta data 30.05.2015 - 12:50
fonte
0

Hai visto che c'è un problema quando si usa il tempo come parte del valore quando si crea un hash: il tempo cambia continuamente. Ma c'è qualche utilità nell'usarlo in un token csrf. La soluzione per consentire piccole variazioni è non hash i valori per ottenere il token, ma invece utilizzare la crittografia simmetrica di una rappresentazione del tempo insieme ad altri valori.

Tuttavia, usare le sessioni è solitamente più ragionevole. E se hai "utenti", "password", per definizione hai una sessione e quindi devi fare la gestione dello stato. Non c'è davvero alcun motivo per non utilizzare la sessione per mantenere i token csrf.

    
risposta data 30.05.2015 - 16:27
fonte

Leggi altre domande sui tag