Usar AntiForgeryToken de MVC3 en HTTP GET para evitar la vulnerabilidad CSRF de Javascript

Con respecto a este blog de Haacked , dudo en implementar las soluciones de secuestro anti-JSON GET propuestas desde

  1. Las soluciones recomendadas para mitigar el secuestro JSON implican POSTS JSON que no son REST para OBTENER datos

  2. La solución alternativa (envoltura de objetos) causa problemas con controles de terceros a los que no tengo acceso de código fuente.

  3. No puedo encontrar una implementación verificada por la comunidad que implemente la Solución alternativa (que se detalla a continuación) sobre cómo redactar el token de seguridad o entregarlo de forma segura dentro de la página web. Tampoco pretenderé ser un experto suficiente para implementar mi propia implementación.

  4. No se puede confiar en los encabezados de referencia

Fondo

Este blog describe un problema de CSRF con respecto al secuestro de JSON y recomienda utilizar los POST de JSON para OBTENER datos. Debido a que el uso de HTTP POST para OBTENER datos no es muy REST-full, busco una solución RESTfull más que permita acciones de REST por sesión o por página.

Otra técnica de mitigación es envolver datos JSON en un objeto como se describe aquí . Me temo que esto puede retrasar el problema, hasta que se encuentre otra técnica.

Implementación alternativa

Para mí, parece natural ampliar el uso de AntiForgeryToken de ASP.NET MVC con jET de HTTP jQuery para mi JSON.

Por ejemplo, si obtengo algunos datos confidenciales, según el enlace Haacked anterior, el siguiente código es vulnerable:

$.getJSON('[url]', { [parameters] }, function(json) { // callback function code }); 

Acepto que no es RESTfull obtener datos utilizando la solución POST recomendada. Mi idea es enviar un token de validación en la URL. De esta forma, el atacante al estilo CSRF no sabrá la URL completa. En caché, o no en caché, no podrán obtener los datos.

A continuación hay dos ejemplos de cómo se podría hacer una consulta JSON GET. No estoy seguro de qué implementación es más efectiva, pero puedo adivinar que la primera es más segura de los servidores proxy errantes que guardan en caché esta información, lo que la hace vulnerable a un atacante.

http: // localhost: 54607 / Inicio / AdminBalances / ENCODEDTOKEN-TOKEN-HERE

o

http: // localhost: 54607 / Home / AdminBalances? ENCODEDTOKEN-TOKEN-HERE

… que bien podría ser AntiForgeryToken de MVC3, o una variante ( ver swt ) del mismo. Este token se establecerá como un valor en línea en cualquier formato de URL que se elija arriba.

Ejemplos de preguntas que me impiden rodar mi propia solución

  1. ¿Qué formato de URL (arriba) usaría para validar JSON GET (barra oblicua, interrogante, etc.) Responderá un proxy a http: // localhost: 54607 / Home / AdminBalances con http: // localhost: 54607 / Home / AdminBalances? ¿Datos ENCODEDTOKEN-TOKEN-HERE ?

  2. ¿Cómo entregarías ese token codificado a la página web? En línea, o como una variable de página?

  3. ¿Cómo redactarías el token? ¿Construido en AntiforgeryToken, o por algún otro medio?

  4. AntiForgeryToken usa una cookie. ¿Se usaría / necesitaría una cookie de respaldo en este caso? ¿HTTP solo? ¿Qué pasa con SSL junto con HTTP solo?

  5. ¿Cómo configuraría los encabezados de su caché? Algo especial para Google Web Accelerator (por ejemplo)

  6. ¿Cuáles son las implicaciones de simplemente hacer que JSON solicite SSL?

  7. ¿Debería la matriz JSON devuelta aún estar envuelta en un objeto solo por razones de seguridad?

  8. ¿Cómo interoperará esta solución con las funciones de plantilla y vinculación de datos de Microsoft?

Las preguntas anteriores son las razones por las que no estoy avanzando y haciendo esto yo mismo. Sin mencionar que probablemente haya más preguntas en las que no haya pensado, y sin embargo son un riesgo.

Asp.net MVC AntiForgeryToken no funcionará a través de HTTP GET, ya que depende de las cookies que dependen de HTTP POST (utiliza la técnica ” Doble envío de cookies ” descrita en la Hoja de referencia de prevención de XSRF de OWASP). También puede proteger adicionalmente las cookies enviadas al cliente estableciendo el como httponly , para que no puedan ser falsificadas a través de un script.

En este documento puede encontrar varias técnicas que pueden usarse para prevenir XSRF. Parece que el que describió podría caer en el Enfoque 1. Pero tenemos un problema sobre cómo recuperar la sesión en el servidor cuando se utiliza la solicitud Ajax HTTP GET dado que las cookies no se envían con la solicitud. Por lo tanto, también debería agregar un identificador de sesión a la URL de su acción (es decir, a las sesiones sin cookies, que son más fáciles de secuestrar). Por lo tanto, para realizar un ataque, el atacante solo necesitaría conocer la URL correcta para realizar la solicitud GET.

Quizás una buena solución sería almacenar los datos de la sesión usando alguna clave del certificado SSL de los usuarios (por ejemplo, el certificado thumb-print). De esta forma, solo el propietario del certificado SSL podría acceder a su sesión. De esta forma, no necesita utilizar cookies y no necesita enviar identificadores de sesión a través de los parámetros de cadena de consulta.

De todos modos, deberá desplegar su propia protección XSRF si no desea utilizar HTTP POST en Asp.net MVC.

Llegué a este problema y la solución no fue tan trivial, sin embargo, hay un blog fantástico para que comiences, que se puede utilizar con get y post ajax.

http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC

Si coloca lo siguiente en el espacio de nombre global, todas sus publicaciones / visitas pueden aprovechar que tiene un token anti falsificación y no tiene que modificar sus llamadas ajax. Crea un elemento de entrada en una página común.

 
@Html.AntiForgeryToken()

El siguiente javascript leerá el tokken anti falsificación y lo agregará al encabezado de la solicitud.

 // Wire up the global jQuery ajaxSend event handler. $(document).ajaxSend(namespace.ajax.globalSendHandler); //  // Global handler for all ajax send events. //  namespace.ajax.globalSendHandler = function (event, xhr, ajaxOptions) { // Add the anti forgery token xhr.setRequestHeader('__RequestVerificationToken', $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val()); }; 
    Intereting Posts