it-swarm-eu.dev

Qual è il modo corretto di implementare i token di modulo anti-CSRF?

Sono pienamente consapevole di CSRF e ho già implementato alcuni moduli sicuri, ma non sono mai stato soddisfatto dei risultati.

Ho creato token come md5 di nome utente, informazioni sul modulo e salt e l'ho memorizzato in una sessione. Questo ha un problema con la navigazione a schede (può essere risolto mantenendo un array di hash attivi) e con i tempi. Vorrei che i miei hash funzionassero solo per es. 10 minuti, ma come posso inserire una variabile correlata al tempo nell'hash?

Qualcuno può indicarmi una buona risorsa che descrive come rendere correttamente la sicurezza CSRF?

34
naugtur

Il modo migliore per costruire correttamente la protezione CSRF:

Non farlo.

I framework più comuni hanno già questa protezione integrata (ASP.NET, Struts, Ruby credo), o ci sono librerie esistenti che sono già state controllate. (Es. CSRFGuard di OWASP ).

Un'altra opzione, a seconda del contesto, è applicare la riautenticazione dell'utente, ma solo per operazioni specifiche e sensibili.


Secondo i tuoi commenti, se hai bisogno di implementarlo da solo, la tua soluzione non è poi così male, ma la semplificherei.
Puoi generare un nonce crittografico (abbastanza a lungo), archiviarlo nella memoria della sessione e cambiarlo ogni X minuti (memorizzi anche il tempo di scadenza nella sessione). In ogni modulo, includere il nonce in un campo modulo nascosto e confrontare tale valore quando il modulo viene pubblicato.
Se il token del modulo corrisponde, sei a posto. In caso contrario, puoi accettare ad es. anche il token precedente, per gestire i casi Edge.

Anche se devo dire che ho visto troppi tentativi falliti di implementarlo da soli, per raccomandare davvero questo percorso. Stai ancora meglio trovare un pacchetto minimo per farlo per te.

25
AviD

C'è una buona spiegazione su OWASP: OWASP CSRF Prevention Cheat Sheet

In breve, dicono che ci sono due modi:

  1. Aggiungi un token casuale a ciascuna sessione utente. Solo se questo token è presente e corretto verranno applicate le modifiche, altrimenti la richiesta dovrebbe essere respinta. È importante che il token venga inviato solo con una POST, poiché le richieste GET possono trasferire il token in posizioni diverse (cronologia del browser, file di registro, ecc.).

    È anche possibile generare un token per richiesta, ma ciò comporta problemi di usabilità. Ad esempio, il pulsante Indietro non funzionerebbe più correttamente. Ma ovviamente la sicurezza sarebbe aumentata.

    Assicurati anche (per migliorare ulteriormente la sicurezza) che il token sia inviato solo su TLS, quindi non ci sarà nessun uomo nei problemi intermedi.

  2. L'altra opzione consiste nell'utilizzare una sorta di challenge-response (ad esempio CAPTCHA o token una tantum).

La pagina OWASP elenca anche alcune misure che non funzionano. Questi sono

  • Utilizzo di cookie (segreti)
  • Non usare richieste GET
  • Transazioni a più passaggi
  • Riscrittura URL
27
Andreas Arnold

Oltre alla risposta di @Andreas Arnold c'è un'alternativa. Ho implementato il Encrypted Token Pattern da OWasp.

Oltre a prevenire gli attacchi CSRF, ha l'ulteriore vantaggio di implementare la sicurezza degli oggetti.

Solo coloro che sono autorizzati a modificare oggetti possono farlo. Altri non avranno il testo o la chiave di cifratura corretti/validi. Di solito crittografo sessionId, timestamp, userId e/o recordId.

timestamp impedisce replayAttacks. sessionid isola solo le modifiche a questa sessione userId isola le modifiche solo a questo utente. Se includi recordId, a spese dell'elaborazione aggiuntiva otterrai maggiore sicurezza.

3
Nasir