it-swarm-es.com

¿Cuál es la forma correcta de implementar tokens de formulario anti-CSRF?

Soy plenamente consciente de CSRF y ya he implementado algunos formularios seguros, pero todavía no he estado satisfecho con los resultados.

Creé tokens como un md5 de nombre de usuario, información de formulario y un salt y lo almacené en una sesión. Esto tiene un problema con la navegación por pestañas (se puede solucionar manteniendo una matriz de hashes activos) y con el tiempo. Me gustaría que mis hashes funcionen solo por ej. 10 minutos, pero ¿cómo pongo una variable relacionada con el tiempo en el hash?

¿Alguien puede señalarme un buen recurso que describa cómo hacer la seguridad CSRF correctamente?

34
naugtur

La mejor manera de construir la protección CSRF correctamente:

No lo hagas.

Los marcos más comunes ya tienen esta protección integrada (ASP.NET, Struts, Ruby creo), o hay bibliotecas existentes que ya han sido examinadas (por ejemplo CSRFGuard de OWASP ).

Otra opción, dependiendo de su contexto, es exigir 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 lo 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 caducidad 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 la ficha de formulario coincide, está claro. Si no, puede aceptar, p. el token anterior también, para manejar los casos Edge.

Aunque debo decir que he visto demasiados intentos fallidos de implementar esto solo, realmente recomiendo este camino. Todavía es mejor encontrar un paquete mínimo para hacer esto por usted.

25
AviD

Hay una buena explicación sobre OWASP: OWASP CSRF Prevention Cheat Sheet

En resumen, dicen que hay dos formas:

  1. 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 ser rechazada. 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 lleva a problemas de usabilidad. Por ejemplo, el botón Atrás ya no funcionaría correctamente. Pero, por supuesto, la seguridad aumentaría.

    También asegúrese (para mejorar aún más la seguridad) de que el token solo se envíe a través de TLS, para que no haya ningún problema intermedio.

  2. La otra opción es usar algún tipo de desafío: respuesta (por ejemplo, CAPTCHA o tokens únicos).

La página OWASP también enumera algunas medidas que no funcionan. Estos son

  • Usar cookies (secretas)
  • No usar solicitudes GET
  • Transacciones de varios pasos
  • Reescritura de URL
27
Andreas Arnold

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 objetos.

Solo aquellos que están autorizados a modificar objetos, pueden hacerlo. Otros no tendrán el texto o clave de cifrado correcto/válido. Usualmente cifro sessionId, timestamp, userId, y/o recordId.

timestamp evita la repetición de Ataques. sessionid aísla los cambios solo a esta sesión userId aísla los cambios solo a este usuario. Si incluye recordId, a costa de un procesamiento adicional obtendrá más seguridad.

3
Nasir