validate the submitted one name form forgery for anti and asp.net-mvc asp.net-mvc-3 security csrf antiforgerytoken

asp.net mvc - the - RequestVerificationToken no coincide



validate the value of the referer header and use a one time nonce for each submitted form (3)

De mis hallazgos recientes ...

Si configura el tipo de contenido como "application / x-www-form-urlencoded" en la solicitud de ajax, debe poner AFRT en los datos

Si configuras el tipo de contenido como "aplicación / json", el token entra en la propiedad ajax "headers" como se describe en haack.

En el servidor si está buscando el token de tipo de formulario, entonces usar el AntiForgeryRequestTokenAttribute vainilla está bien, pero si quiere validar los tokens enviados en el encabezado, entonces debe llamar a AntiForgeryToken.OnAuthorize ... o lo que sea, pasando el token del cookie (contexto HTTP).

No es fácil, pero si fuera todo el mundo lo estaría haciendo :)

Tengo un problema con el mecanismo anti CRSF MVC. La cookie y la entrada de formulario devuelta no coinciden. Recibo un error cada vez, solo en una página específica. En el resto de la aplicación, funciona bien.

El servidor está devolviendo HTTP 500 Internal Server Error y puedo ver en el registro esta excepción:

[System.Web.Mvc.HttpAntiForgeryException]: {"No se proporcionó un token antifalsificación requerido o no era válido."}

Esta es la entrada oculta que está generando el servidor:

<input name="__RequestVerificationToken" type="hidden" value="QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2+ZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io/0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld">

Y esta es la galleta devuelta:

Set-Cookie:__RequestVerificationToken_L2VGbG93=skmTAVI8HCbfxDS+xhioIMIISL3UOBI7qJM1JbHjTtAqKl4W70pDUcTKMm0p3R3mrHDziE8vXw0C0OO4HArzWO1/e6py+v/cFdbe9maFgjl4jMiZ9Wc4YIhC6+IUXkk6yqJDJ8dCIr8qtGaYcD9IX+m7/SlVhu521KQSWJYRcaY=; path=/; HttpOnly

Cuando examino lo que envía el servidor, la cookie es exactamente la misma, pero creo que la carga tiene una codificación diferente:

__RequestVerificationToken:QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2%2BZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io%2F0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld

Las diferencias están en dos caracteres que aparecen codificados:

/ -> %2F + -> %2B

Esas son las únicas diferencias que puedo encontrar entre el campo de entrada oculto y la carga útil de la publicación.

¿Cuál podría ser el problema que está causando que ValidateAntiForgeryToken falle al verificar el token?

Saludos.


He tenido y he resuelto varios problemas con ValidateAntiForgeryToken últimamente, así que compartiré mis hallazgos con usted.

Salt : Como mencionas que esto solo sucede en una sola página, mi mejor estimación es que estás usando diferentes valores de salt en tus llamadas a Html.AntiForgeryToken(salt) y ValidateAntiForgeryToken(salt) llamadas.

AJAX : como ha dicho otra respuesta, usar AJAX puede requerir trabajo adicional para garantizar que el token esté incluido en el POST. Esta es mi solución favorita , simple y automática para agregar el token a todas las solicitudes POSTE de AJAX .
Sin embargo, en tu pregunta, declaras que has verificado que el token está enviando. ¿Has verificado que solo estás enviando el token una vez? Descubrí que una llamada mía de AJAX estaba enviando el token dos veces, lo que combinaba los valores y hacía que fallara.

Clave de máquina y cookies : este problema es feo, fácil de detectar (provoca excepciones), pero no es muy intuitivo. Las cookies y tokens de validación se codifican y decodifican utilizando una "clave de máquina" única. Esto significa que si tiene una granja de servidores o cambia su servidor, su cookie ya no será válida. Cerrar el navegador soluciona el problema (porque la cookie es una cookie de sesión). Sin embargo, algunas personas dejan las ventanas de su navegador abiertas en el fondo durante mucho tiempo.
La solución es establecer una "clave de máquina" en su archivo de configuración. Esto le indicará a MVC que use la misma clave en todos los servidores, asegurando que la cookie se pueda descifrar en cualquier lugar.

Errores de codificación : utilizando una utilidad de prueba llamada jMeter, intentamos realizar pruebas de carga en nuestras páginas, solo para descubrir que tenía un error que causaba que nuestro token tuviese 2 " extra " alrededor del valor.
¡La solución es reducir tu confianza en tus herramientas! Pruebe en un navegador, y si eso funciona, cree una prueba que extraiga los valores de token y cookie, y configure un punto de interrupción para verificar los resultados.

Si ninguna de estas cosas funciona para usted, le recomiendo que eche un vistazo al código fuente MVC para ValidateAntiForgeryTokenAttribute , específicamente el método OnAuthorization . Le ayudará a ver los diferentes pasos donde la validación podría fallar. Incluso puede inspeccionar Exception.StackTrace su error para determinar qué parte está fallando.

Como nota al margen , realmente no me gusta la implementación de ValidateAntiForgeryToken en MVC, porque:

  • Hay aproximadamente 5 pasos de verificación que pueden fallar, pero solo hay un mensaje de error genérico.
  • La clase está sellada, por lo que no puede ampliarse con funcionalidad adicional.
  • El método de cifrado es extraño: inicializa una Page y crea un ViewState artificial para cifrar los tokens y las cookies. Parece excesivo.

Así que agarré el código fuente y creé mi propia subclase especializada, que también resultó muy útil para depurar sus problemas, porque podía establecer puntos de interrupción en los métodos de validación, y era muy fácil determinar qué paso de validación estaba fallando. .


Si esto se envía como una solicitud de Ajax, entonces la configuración actual del marco no está construida para hacerlo de forma natural.

Afortunadamente, Phil Haak escribió una buena publicación de blog sobre cómo lidiar con CSRF y Ajax -> Prevención de CSRF con Ajax, que detalla algunos detalles sobre cómo usar el marco existente y cómo modificarlo para que funcione para Ajax / Json.