Necesita que el token se envíe en la solicitud fuera del mecanismo de la cookie (por ejemplo, datos POST). Si las sesiones se administran a través de una ID de sesión contenida dentro de una cookie, su enfoque no impide el CSRF.
En su implementación actual:
- guardar el token en la sesión;
- guardar el token en la cookie del cliente a través del encabezado Set-Cookie.
Esto tendrá el efecto de que el token se guarde en dos ubicaciones, pero ambas ubicaciones se identificarán por los valores de las cookies.
por ejemplo si el token es " 12345678
" se guardará en la sesión (pseudocódigo):
Session["SessionCSRFToken"] = "12345678";
y en cookies
Cookies.Add("CSRFToken", "12345678");
Sin embargo, para guardar el valor en la sesión, el marco de la aplicación web creará una cookie para identificar la sesión, por lo que obtendrá dos cookies:
Set-Cookie: CSRFToken=12345678;
Set-Cookie: SessionID=987654321;
Si un usuario inicia sesión en su sitio web en www.foo.com
y luego el usuario visita www.evil.com
, podría haber una etiqueta oculta form
incrustada en la página de www.evil.com
(posiblemente dentro de un IFrame oculto) que es enviado automáticamente por JavaScript:
<form method="post" action="https://www.foo.com/Account/DeleteAccount">
</form>
Cuando el navegador envíe automáticamente el formulario, ambas cookies se enviarán junto con la solicitud
( CSRFToken=12345678
, SessionID=987654321
) y su token de cookie ( CSRFToken
) y token de sesión ( SessionCSRFToken
) coincidirán y el efecto será que la cuenta del usuario está cerrada en su sistema sin su conocimiento.
Para evitar esto, necesita almacenar un token CSRF en la propia página (por ejemplo, dentro de una entrada oculta). De esta manera, su formulario solo se puede enviar de la siguiente manera:
<form method="post" action="/Account/DeleteAccount">
<input type="hidden" name="CSRFToken" value="12345678" />
</form>
Ahora www.evil.com
no tiene forma de incluir la entrada oculta en su propio HTML, ya que no tienen forma de saber el valor de CSRFToken
. El valor de CSRFToken
puede ser el mismo que la cookie (ahora ya no se necesita el valor de la sesión), pero solo debe generarse una vez que haya una sesión previa al usuario (no es necesario regenerar constantemente el valor).
Para cada POST
simplemente necesitas asegurarte de que Request.Form["CSRFToken"] == Request.Cookies("CSRFToken")
.