Se lo fai per ogni richiesta modulo - quindi si rimuove sostanzialmente la possibilità per gli attacchi CSRF a verificarsi & è possibile risolvere un altro problema comune: forma multipla presentazione
In termini semplici - la vostra applicazione accetterà solo modulo di input se l'utente ha richiesto il modulo prima dell'invio.
scenario normale: utente A va al tuo sito web, e chiede Forma A, viene data forma A più un codice univoco per il modulo A. Quando l'utente invia Forma A, lui/lei deve includere il codice unico che era solo per modulo A.
attacco CSRF scenario: utente a va al tuo sito web, e chiede modulo A. Nel frattempo si visita un altro sito "cattivo", che tenta un attacco CSRF su di loro, inducendole a invia per un falso Modulo B.
Ma il tuo sito web sa che l'Utente A non ha mai richiesto il Modulo B - e quindi anche Se hanno il codice univoco per il modulo A, il modulo B verrà rifiutato perché non hanno un codice univoco di tipo B, solo un codice di forma A. Il tuo utente è al sicuro e puoi dormire sonni tranquilli durante la notte.
Ma se lo fai come token generico, della durata di un'ora (come hai postato sopra), allora l'attacco sopra potrebbe funzionare, nel qual caso non hai ottenuto molto con la tua protezione CSRF. Questo perché l'applicazione non sa che il modulo B non è mai stato richiesto in primo luogo. È un token generico. Il PUNTO TUTTO della prevenzione CSRF è quello di rendere ogni modulo token univoco a quella forma
Edit: perché lei ha chiesto per ulteriori informazioni: 1 - non dovete farlo per ogni modulo di richiesta, si può fare per ora/sessione ecc. Il punto è un valore segreto che viene fornito all'utente e rinominato sul reso.Questo valore non è conosciuto da un altro sito Web e pertanto non può presentare una forma falsa.
Così si sia generare il token per ogni richiesta, o per ogni sessione:
// Before rendering the page:
$data['my_token'] = md5(uniqid(rand(), true));
$_SESSION['my_token'] = $data['my_token'];
// During page rendering:
<input type="hidden" name="my_token" id="my_token" value="<? php echo $_SESSION['my_token']?>" />
// After they click submit, when checking form:
if ($_POST['my_token'] === $_SESSION['my_token'])
{
// was ok
}
else
{
// was bad!!!
}
e perché è "per forma" - che si voleva ottenere doppie invio di moduli - perché si può pulire il token dopo il primo modulo sottomissione!
Attenzione che la generazione di un nuovo token per richiesta può causare problemi se un utente ha l'applicazione aperta in due finestre di browser diverse contemporaneamente. I token non saranno sincronizzati. –
@ Michael Questo problema potrebbe essere risolto con la tecnologia push, html 5 standard di comunicazione. –
Se non è di alta sicurezza, basta prendere un hash, ad es. dell'ip utente e del suo hash della password. Questo potrebbe non cambiare mai o solo raramente, ma serve comunque al suo scopo poiché un utente malintenzionato non conoscerà la password dell'utente (e se lo fa, non ha bisogno di eseguire un attacco CSRF su di lui) – ThiefMaster