Nuestro grupo de especialistas luego de varios días de investigación y recopilar de datos, dimos con los datos necesarios, queremos que te sea útil en tu plan.
Solución:
Hay una buena explicación en OWASP: OWASP CSRF Prevention Cheat Sheet
En resumen dicen que hay dos formas:
-
Agregue un token aleatorio a cada sesión de usuario. Solo si este token está presente y es correcto, se aplicarán los cambios; de lo contrario, la solicitud debe rechazarse. Es importante que el token solo se envíe con una solicitud POST, ya que las solicitudes GET pueden filtrar el token a diferentes lugares (historial del navegador, archivos de registro, etc.).
También es posible generar un token por solicitud, pero esto genera problemas de usabilidad. Por ejemplo, el botón de retroceso ya no funcionaría correctamente. Pero, por supuesto, se incrementaría la seguridad.
También asegúrese (para mejorar la seguridad aún más) de que el token solo se envíe a través de TLS, para que no haya problemas de intermediarios.
-
La otra opción es usar algún tipo de desafío – respuesta (por ejemplo, CAPTCHA o tokens de una sola vez).
La página de OWASP también enumera algunas medidas que no funcionan. Estos son
- Uso de cookies (secretas)
- No usar solicitudes GET
- Transacciones de varios pasos
- Reescritura de URL
La mejor forma de crear una protección CSRF correctamente:
No lo hagas.
La mayoría de los marcos comunes ya tienen esta protección incorporada (ASP.NET, Struts, Ruby, creo), o existen bibliotecas que ya han sido examinadas. (por ejemplo, CSRFGuard de OWASP).
Otra opción, dependiendo de su contexto, es hacer cumplir la reautenticación del usuario, pero solo para operaciones específicas y sensibles.
Según sus comentarios, si necesita implementar esto usted mismo, su solución no es tan mala, pero la simplificaría.
Puede generar un nonce criptoaleatorio (lo suficientemente largo), almacenarlo en la memoria de la sesión y cambiarlo cada X minutos (también almacena el tiempo de vencimiento en la sesión). En cada formulario, incluye el nonce en un campo de formulario oculto y compara ese valor cuando se publica el formulario.
Si el token de formulario coincide, está claro. Si no es así, puede aceptar, por ejemplo, el token anterior también, para manejar los casos extremos.
Aunque debo decir que he visto demasiados intentos fallidos de implementar esto por uno mismo, para recomendar realmente este camino. Aún es mejor encontrar un paquete mínimo para hacer esto por usted.
Además de la respuesta de @Andreas Arnold, hay una alternativa. Implementé el Encrypted Token Pattern
de OWasp.
Además de prevenir ataques csrf, tiene la ventaja adicional de implementar la seguridad de los objetos.
Solo aquellos que están autorizados a modificar objetos pueden hacerlo. Otros no tendrán el texto cifrado correcto / válido o key. Yo suelo cifrar sessionId
, timestamp
, userId
y / o recordId
.
timestamp
previene replayAttacks.
sessionid
aísla los cambios en esta sesión solamente
userId
aísla los cambios solo para este usuario. Si incluye recordId
, luego, a costa de un procesamiento adicional, obtiene más seguridad.