json - forgery - csrf example
Usando AntiForgeryToken de MVC3 en HTTP GET para evitar la vulnerabilidad de CSRF de Javascript (2)
El MVC AntiForgeryToken de Asp.net no funcionará a través de HTTP GET, ya que se basa en cookies que se basan en HTTP POST (utiliza la técnica de " Doble envío de cookies " descrita en la Hoja de referencia de prevención OWASP XSRF). También puede proteger adicionalmente las cookies enviadas al cliente configurando como httponly , por lo que no se pueden falsificar mediante un script.
En este documento puede encontrar varias técnicas que se pueden usar para prevenir XSRF. Parece que lo que describiste caería en el Enfoque 1. Pero tenemos un problema sobre cómo recuperar la sesión en el servidor cuando se usa la solicitud Ajax HTTP GET ya que las cookies no se envían con la solicitud. Por lo tanto, también tendría que agregar un identificador de sesión a la URL de su acción (también conocida como sesiones sin cookies, que son más fáciles de secuestrar). Por lo tanto, para realizar un ataque, el atacante solo necesitaría saber la URL correcta para realizar la solicitud GET.
Tal vez una buena solución sería almacenar los datos de la sesión utilizando alguna clave del certificado SSL de los usuarios (por ejemplo, la huella digital del certificado). De esta manera solo el propietario del certificado SSL podría acceder a su sesión. De esta manera, no necesita usar cookies y no necesita enviar identificadores de sesión a través de parámetros de cadena de consulta.
De todos modos, deberá implementar su propia protección XSRF si no desea utilizar HTTP POST en Asp.net MVC.
En lo que respecta a este blog de Haacked , no me atrevo a implementar las soluciones de secuestro anti-JSON GET propuestas desde
Las soluciones recomendadas para mitigar el secuestro de JSON implican POST JSON no REST completos para obtener datos
La solución alternativa (ajuste de objetos) causa problemas con los controles de terceros a los que no tengo acceso con código fuente.
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 componer el token de seguridad o cómo entregarlo de manera segura dentro de la página web. Tampoco pretendo ser un experto suficiente para rodar mi propia implementación.
No se puede confiar en los encabezados de referencia
Fondo
Este blog describe un problema de CSRF relacionado con el secuestro de JSON y recomienda el uso de POST de JSON para obtener datos. Dado que el uso de HTTP POST para obtener datos no está muy lleno de REST, buscaría una solución más RESTfull que habilite acciones REST por sesión o por página.
Otra técnica de mitigación es envolver los 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 extender el uso de ASP.NET MVC''s AntiForgeryToken con jQuery HTTP GET para mi JSON.
Por ejemplo, si obtengo algunos datos confidenciales, según el enlace de Haacked anterior, el siguiente código es vulnerable:
$.getJSON(''[url]'', { [parameters] }, function(json) {
// callback function code
});
Estoy de acuerdo en que no es RESTfull para obtener datos utilizando la solución POST recomendada. Mi pensamiento es enviar un token de validación en la URL. De esa manera, 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 se muestran dos ejemplos de cómo se podría realizar una consulta JSON GET. No estoy seguro de qué implementación es la más efectiva, pero puedo suponer que la primera es más segura de los proxies errantes que almacenan en caché estos datos, lo que los hace vulnerables a un atacante.
http://localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE
o
http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE
... que bien podría ser el AntiForgeryToken de MVC3, o una variante ( ver swt ) del mismo. Este token se establecería como un valor en línea en cualquier formato de URL que se haya elegido anteriormente.
Ejemplo de preguntas que me impiden rodar mi propia solución.
¿Qué formato de URL (arriba) usaría para validar el JSON GET (barra, pregunta, etc.) ¿Responderá un proxy a http://localhost:54607/Home/AdminBalances con http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE datos?
¿Cómo entregaría ese token codificado a la página web? En línea, o como una variable de página?
¿Cómo compondrías el token? ¿Construido en AntiforgeryToken, o por algún otro medio?
El AntiForgeryToken utiliza una cookie. ¿Se usaría / necesitaría una cookie de respaldo en este caso? Sólo HTTP? ¿Qué pasa con SSL en conjunción con HTTP solamente?
¿Cómo configurar sus encabezados de caché? Algo especial para el acelerador de Google (por ejemplo)
¿Cuáles son las implicaciones de solo hacer la solicitud JSON SSL?
¿Debería la matriz JSON devuelta todavía estar envuelta en un objeto solo por razones de seguridad?
¿Cómo se interoperará esta solución con las funciones de creación de datos y vinculación de datos propuestas por Microsoft?
Las preguntas anteriores son las razones por las que no estoy avanzando y haciendo esto por mí mismo. Sin mencionar que es probable que haya más preguntas en las que no haya pensado y que, sin embargo, son un riesgo.
Llegué a este problema y la solución no era tan trivial, sin embargo, hay un blog fantástico para comenzar. Esto se puede usar 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 nombres global, todas sus publicaciones / puntos pueden aprovecharse al tener un token anti falsificación y no tiene que modificar sus llamadas ajax. Crear un elemento de entrada en una página común.
<form id="__AjaxAntiForgeryForm" action="#" method="post">@Html.AntiForgeryToken()</form>
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);
// <summary>
// Global handler for all ajax send events.
// </summary>
namespace.ajax.globalSendHandler = function (event, xhr, ajaxOptions) {
// Add the anti forgery token
xhr.setRequestHeader(''__RequestVerificationToken'', $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val());
};