2009-11-26 21 views
37

Questa è una domanda sulla generazione di token CSRF.Generazione di token CSRF

Generalmente mi piacerebbe generare un token basato su un pezzo unico di dati associato alla sessione dell'utente, e con hash e salato con una chiave segreta.

La mia domanda riguarda la generazione di token quando NON ci sono dati utente unici da utilizzare. Nessuna sessione è disponibile, i cookie non sono un'opzione, l'indirizzo IP e cose di questa natura non sono affidabili.

C'è qualche motivo per cui non posso includere anche la stringa in hash come parte della richiesta? Esempio pseudocodice per generare il token e incorporarlo:

var $stringToHash = random() 
var $csrfToken = hash($stringToHash + $mySecretKey) 
<a href="http://foo.com?csrfToken={$csrfToken}&key={$stringToHash}">click me</a> 

Esempio validazione lato server del CSRF gettone

var $stringToHash = request.get('key') 
var $isValidToken = hash($stringToHash + $mySecrtKey) == request.get('csrfToken') 

La stringa in uso nel hash sarebbe diverso su ogni richiesta. Finché è stato incluso in ogni richiesta, è possibile procedere con la convalida del token CSRF. Poiché è nuovo su ogni richiesta e solo incorporato nella pagina, l'accesso esterno al token non sarebbe disponibile. La sicurezza del token cade quindi su $ mySecretKey essendo nota solo a me.

È un approccio ingenuo? Mi manca qualche motivo per cui questo non può funzionare?

Grazie

+8

La soluzione proposta è vulnerabile agli attacchi di riprodurre.Lo stesso token e combinazione di tasti funzioneranno indefinitamente. – Matthew

risposta

2

CSRF Token scopo di impedire (involontarie) modifiche di dati, che sono di solito applicati agli richieste POST.

Pertanto, è necessario includere un token CSRF per ogni richiesta che modifica i dati (richiesta GET o POST).

La mia domanda è per quanto riguarda token generatori quando non c'è dati utente univoco da utilizzare. Non sono disponibili sessioni , i cookie non sono un'opzione , l'indirizzo IP e cose di quello natura non sono affidabili.

Quindi creare semplicemente un ID utente univoco per ciascun visitatore. Includere quell'id in un cookie o negli URL (se i cookie sono disabilitati).

Edit:

Si consideri il seguente evento:

Hai effettuato il login al proprio account facebook e poi è entrato a qualche sito arbitrario.

In questo sito Web è presente un modulo inviato, che indica al browser di inviare una richiesta POST al proprio account Facebook.

Tale richiesta POST può modificare la password o aggiungere un commento, ecc., Perché l'applicazione Facebook ti ha riconosciuto come utente registrato &. (a meno che non ci sia un altro meccanismo di blocco, come CAPTCHA)

+0

Aggiunta di una parte del token a un URL e l'altra metà nel modulo significa nessuna protezione. – blowdart

+0

Scusa ma cosa intendi? Non ho scritto che ... – Dor

+0

Certo che hai fatto, "Includere quell'ID in un cookie o negli URL (se i cookie sono disabilitati)." - tu dici di inserire l'id nell'URL, semplicemente non è sicuro. – blowdart

-4

CSRF utilizza la sessione dell'utente, quindi, se non ne hai uno, non c'è CSRF.

+0

Sebbene questa risposta non sia affatto utile, è tecnicamente corretta. –

25

C'è qualche motivo per cui non posso includere anche la stringa in hash come parte della richiesta?

I token CSRF hanno due parti. Il token incorporato nel modulo e un token corrispondente da qualche altra parte, sia esso in un cookie, memorizzato in una sessione o altrove. Questo uso di altrove impedisce che una pagina sia autonoma.

Se si include la stringa in hash nella richiesta, la richiesta è autonoma, quindi la copia del modulo è tutto ciò che un utente malintenzionato deve eseguire, in quanto ha entrambe le parti del token e quindi non c'è alcuna protezione.

Anche inserendolo nell'URL del modulo significa che è autonomo, l'autore dell'attacco copia semplicemente il modulo e l'URL di invio.

+0

È necessario ricordare il token memorizzato sul server ... –

+14

No, non lo si. Una metà potrebbe essere mantenuta in sessione o potrebbe essere eliminata tramite un cookie. Non deve essere necessariamente memorizzato sul server, di solito è basato sui cookie, quindi non è necessario affidarsi alle sessioni di abilitazione. – blowdart

+0

Secondo OWASP, questa è solo una * attenuazione * chiamata "double submit cookies" https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Double_Submit_Cookies – zb226

1

Basta semplicemente avere lo stesso "token" nell'URL/modulo e nel cookie. Ciò significa che potresti avere la tua pagina che imposta il cookie token su qualsiasi cosa desideri (preferibilmente un valore casuale) da JavaScript e poi passa lo stesso valore in tutte le richieste che vanno al tuo server (come un URI? Param o form- campo). Non è necessario che il tuo server generi il cookie.

Questo è sicuro finché crediamo che il browser non consenta alle pagine di un dominio di modificare/leggere i cookie per altri domini e si presume che sia abbastanza sicuro oggi.

Avere il server che genera il token presuppone che questo token possa essere trasmesso in sicurezza al browser senza essere rilevato da alcun tentativo CSRF (perché rischiare?). Sebbene tu possa mettere più logica in un token generato dal server, ma per prevenire CSRF non c'è bisogno.

(Se mi sbaglio qui per favore fatemelo sapere)

0

penso che l'idea migliore per fare hash basato su HMAC, vale a dire rendere hash cifrato della password da parte di alcuni questa sequenza: nome utente + id_utente + timestamp. Ogni richiesta dell'hash deve essere diversa, deve essere il timestamp se non si desidera ottenere una semplice riproduzione dell'hash in attacco.

0

che voglio dire il vostro approccio funziona, perché l'attacco CSRF l'attaccante utilizza il browser della vittima per falsificare uno stato di accesso, perché possono farlo? perché per la maggior parte dei server il controllo di sessione è basato su un SessionID in cookie e cookie è un dato che verrà automaticamente allegato a una richiesta HTTP inviata al server.

Di conseguenza, ci sono due fattori chiave per la difesa CSRF

  1. generare un token sfida, e richiedono il programma e passarlo al server in modo non-cookie, o param URL o forma POST è ok.
  2. Tieni il token al sicuro come quello che hai fatto al SessionID, per esempio usando SSL.

vi consiglio di leggere CSRF Prevention Cheat Sheet