¿Por qué actualizar el token CSRF por solicitud de formulario?

82

En muchos tutoriales y guías veo que un token CSRF debe actualizarse por solicitud. Mi pregunta es ¿por qué tengo que hacer esto? ¿No es un solo token CSRF por sesión mucho más fácil que generar uno por solicitud y realizar un seguimiento de los solicitados?

La generación del token en una base por solicitud no parece mejorar la seguridad más allá de lo que un token por sesión ya haría. El único argumento parece ser la protección XSS, pero esto no se aplica, ya que cuando tienes una vulnerabilidad XSS, el script podría leer nuevos tokens de todos modos.

¿Cuáles son los beneficios de generar nuevos tokens por solicitud?

    
pregunta Philipp 20.10.2012 - 13:15
fuente

8 respuestas

95

Por las razones ya comentadas, no es necesario generar un nuevo token por solicitud. Aporta una ventaja de seguridad casi nula y le cuesta en términos de facilidad de uso: con un solo token válido a la vez, el usuario no podrá navegar la aplicación web normalmente. Por ejemplo, si presionan el botón "atrás" y envían el formulario con nuevos valores, la presentación fallará y probablemente los saludará con un mensaje de error hostil. Si intentan abrir un recurso en una segunda pestaña, encontrarán que la sesión se divide aleatoriamente en una o ambas pestañas. Por lo general, no vale la pena mutilar la facilidad de uso de su aplicación para satisfacer este requisito sin sentido.

Hay hay un lugar donde vale la pena emitir un nuevo token CSRF: en cambio de principal dentro de una sesión. Eso es, principalmente, en el inicio de sesión. Esto es para evitar un ataque de fijación de sesión que lleve a una posibilidad de ataque CSRF.

Por ejemplo: el atacante accede al sitio y genera una nueva sesión. Toman la identificación de la sesión y la inyectan en el navegador de la víctima (por ejemplo, a través de la escritura de una cookie de un dominio vecino vulnerable, o utilizando otra vulnerabilidad como las URL de jsessionid), y también inyectan el token CSRF en un formulario en el navegador de la víctima. Esperan a que la víctima inicie sesión con ese formulario y luego usan otra publicación de formulario para hacer que la víctima realice una acción con el token CSRF aún en vivo.

Para evitar esto, invalide el token CSRF y emita uno nuevo en los lugares (como inicio de sesión) que ya está haciendo lo mismo con el ID de sesión para evitar ataques de reparación de sesión.

    
respondido por el bobince 21.10.2012 - 22:31
fuente
18

Descripción general. El consejo estándar es utilizar un token CSRF único que sea único para cada solicitud. ¿Por qué? Debido a que un token por solicitud es un poco más resistente a ciertos tipos de errores de implementación que un token por sesión. Esto hace que los tokens por solicitud sean la mejor opción para el desarrollo de nuevas aplicaciones web. Además, ningún auditor de seguridad lo molestará con el uso de un token CSRF por solicitud.

Si eres un desarrollador de aplicaciones web, esto es todo lo que necesitas saber, y puedes dejar de leer aquí. Pero si es un experto en seguridad que se pregunta sobre los fundamentos detallados de este consejo, o si se pregunta qué tan grande es el riesgo si usa un token por sesión, siga leyendo ...

Profundizando un poco más. La verdad es que, si no tiene otras vulnerabilidades en su sitio web, un solo token CSRF por sesión está bien. No hay ninguna razón por la que necesariamente tengas para generar un token CSRF nuevo por solicitud.

Esto se demuestra por el hecho de que también encontrará expertos de seguridad acreditados que dicen que otra forma razonable de defenderse contra CSRF es usar el envío doble de cookies: en otras palabras, usa un Javascript del lado del cliente que calcula un hash de la cookie de sesión y agrega eso a cada solicitud POST, tratando el hash como el token CSRF. Puede ver que esto esencialmente genera sobre la marcha un token CSRF que es el mismo para toda la sesión.

Por supuesto, conozco el argumento por el que algunas personas pueden recomendar generar un nuevo token CSRF para cada solicitud. Están pensando que, si también tiene una vulnerabilidad XSS en su sitio web, si usa un solo token CSRF por sesión, será fácil usar XSS para recuperar el token CSRF, mientras que si genera un token CSRF nuevo por solicitud, Tomará más trabajo para recuperar el token CSRF. Personalmente, no considero que este argumento sea terriblemente convincente. Si tiene una vulnerabilidad XSS en su sitio, aún es posible recuperar tokens CSRF, incluso si genera un token CSRF nuevo para cada solicitud, solo se necesitan algunas líneas adicionales de Javascript malintencionado. De cualquier manera, si tienes una vulnerabilidad XSS en tu sitio y te enfrentas a un atacante serio y experto, es difícil garantizar la seguridad, sin importar cómo generes tus tokens CSRF.

En general, no se debe dejar de generar un nuevo token CSRF para cada solicitud. Y tal vez es mejor hacerlo de esa manera, solo para que los auditores de seguridad se retiren de su espalda. Pero si ya tiene una aplicación heredada que usa un solo token CSRF para toda la sesión, gastar el dinero para convertirlo para generar un nuevo token CSRF para cada solicitud probablemente no sería muy alto en mi lista de prioridades: apuesto a que podría encontrar otros usos para ese dinero y la energía del desarrollador que mejoraría aún más la seguridad.

    
respondido por el D.W. 21.10.2012 - 01:55
fuente
12

XSS se puede usar para leer un token CSRF, incluso si es un token de envío único, es un juego de niños. Es probable que esta recomendación de un solo token de envío provenga de alguien que no entienda CSRF.

La única razón para usar un "token de envío único" es si desea evitar que el usuario haga clic en enviar accidentalmente dos veces. Un buen uso de esto es evitar que el usuario haga clic en "pagar" dos veces y que accidentalmente le cobre al cliente dos veces.

Un CAPTCHA o la solicitud de la contraseña actual del usuario se puede usar como una medida anti-csrf que XSS no puede omitir.

Recomiendo leer el Hoja de trucos de prevención de CSRF .

    
respondido por el rook 20.10.2012 - 20:24
fuente
6

Si el token es el mismo en toda la sesión, es posible que un atacante filtre un token de una página y lo use para una acción diferente.

Por ejemplo, podría usar un iframe para cargar una página y luego extraer el token con una vulnerabilidad XSS. Desde allí, puede usar ese token para enviar un formulario de cambio de contraseña

El uso de un token por solicitud en lugar de uno para toda la sesión lo hace más difícil, pero no impide el CSRF. Un atacante puede simplemente aprovechar un XSS para leer el token de la página y luego dispararlo. Sin embargo, si el token es global en lugar de restringido a esa página individual, un atacante puede apuntar a cualquier página para robar el token. El uso de tokens separados para cada solicitud hace que esto sea mucho más difícil.

    
respondido por el Polynomial 20.10.2012 - 15:37
fuente
3

Además de las otras respuestas, podría ser aconsejable actualizar el token también si su servidor es susceptible al ataque BREACH .

Esto requiere las siguientes tres condiciones:

  
  • Servir desde un servidor que usa compresión de nivel HTTP
  •   
  • Refleja la entrada del usuario en los cuerpos de respuesta HTTP
  •   
  • Refleja un secreto (como un token CSRF ) en los cuerpos de respuesta HTTP
  •   

Para mitigar el INCREMENTO, deberá actualizar el token CSRF en la solicitud GET que carga un formulario para invalidar todos los tokens anteriores. De esta manera, un MITM (Man-In-The-Middle) que crea solicitudes adicionales para descubrir el token en la página obtendrá un token diferente cada vez. Esto significa que el usuario real no podrá enviar el formulario en una situación MITM.

Por supuesto, también necesitas las otras dos condiciones para que se cumpla. Probablemente sería más fácil mantener un token CSRF por sesión y deshabilitar la compresión a nivel de HTTP para cualquier página que sirva formularios.

    
respondido por el SilverlightFox 30.11.2015 - 11:45
fuente
1

No es un hecho muy conocido, pero la comparación normal de cadenas es vulnerable a los ataques de tiempo ( como este . En pocas palabras, las operaciones de comparación de cadenas normales ( == o === ) compararán dos cadenas de caracteres de izquierda a derecha y devolverán falsas una vez que hayan encontrado cualquier carácter que no sea igual en una posición dada en ambas Esto proporciona una diferencia minúscula en el tiempo que se ha demostrado detectable .

Al utilizar un ataque de tiempo para probar todos los caracteres posibles para cada posición, es posible determinar cuál es el token real. Al crear un nuevo token cada vez que se envía una solicitud con un token, se puede evitar este ataque.

Por supuesto, esto solo funciona si también vuelve a crear el token si se ha enviado un token no válido , lo que puede ser indeseable. Por lo tanto, es mejor que solucione esto utilizando una función de comparación de cadenas insensible al tiempo como esta .

    
respondido por el user2428118 17.07.2015 - 12:45
fuente
0

Una de las razones para querer cambiar el token CSRF por solicitud es mitigar la pérdida de compresión del token. Lo que quiero decir con eso es que si el atacante Eve puede inyectar datos en una página que contiene el token al que se envía la página comprimida, Eve puede adivinar el primer carácter de la cadena que recibe un conjunto de datos más pequeño para la página, sabiendo que ella acertó y luego ir. en el siguiente personaje.

Esto es similar a un ataque de tiempo.

En este momento no hay ninguna razón (que yo sepa) para cambiar el token si solo se envía en los encabezados HTTP.

Otro método es cambiar el token tan pronto como se descubra una solicitud fallida, pero esto podría tener problemas con el hecho de que el usuario no pueda enviar ningún formulario.

    
respondido por el edruid 23.04.2015 - 17:30
fuente
-1

Si se usa el mismo token para toda la sesión, es probable que el atacante pueda secuestrar el token utilizando XSS y usar la sesión de la víctima para realizar algunas actividades maliciosas, como cambiar la contraseña .

Pueden intercambiar contraseñas colocando un iframe en el sitio que está utilizando.

Por lo tanto, es mejor usar un token por solicitud para evitar que el atacante obtenga acceso a ese token.

    
respondido por el Bhuvanesh 17.07.2015 - 09:37
fuente

Lea otras preguntas en las etiquetas