practices for disable best security http rest authorization csrf

for - spring security csrf() disable()



¿Cómo prevenir CSRF en una aplicación RESTful? (6)

La falsificación de solicitudes cruzadas (CSRF) normalmente se evita con uno de los siguientes métodos:

  • Check referer - RESTful pero no confiable
  • inserte el token en el formulario y almacene el token en la sesión del servidor, no realmente RESTful
  • URI crípticos de una sola vez: no RESTful por la misma razón que los tokens
  • envíe la contraseña manualmente para esta solicitud (no la contraseña en caché utilizada con la autenticación HTTP) - RESTful pero no conveniente

Mi idea es usar un secreto de usuario, un identificador críptico pero estático y JavaScript para generar tokens.

<form method="POST" action="/someresource" id="7099879082361234103"> <input type="hidden" name="token" value="generateToken(...)"> ... </form>

  1. GET /usersecret/john_doe obtenido por el JavaScript del usuario autenticado.
  2. Respuesta: OK 89070135420357234586534346 Este secreto es conceptualmente estático, pero se puede cambiar cada día / hora ... para mejorar la seguridad. Esta es la única cosa confidencial.
  3. Lea la identificación críptica (pero estática para todos los usuarios!) Con JavaScript, generateToken(7099879082361234103, 89070135420357234586534346) junto con el secreto del usuario: generateToken(7099879082361234103, 89070135420357234586534346)
  4. Envíe el formulario junto con el token generado al servidor.
  5. Como el servidor conoce el secreto de usuario y el id. De formulario, es posible ejecutar la misma función generateToken que el cliente antes de enviar y comparar ambos resultados. Solo cuando ambos valores sean iguales, la acción será autorizada.

¿Pasa algo con este enfoque, a pesar de que no funciona sin JavaScript?

Apéndice:


¿Pasa algo con este enfoque, a pesar de que no funciona sin JavaScript?

Su secreto de usuario no es un secreto si lo envía al cliente. Por lo general, usamos esos secretos para generar hashes y los enviamos con el formulario, y los esperamos para compararlos.

Si desea ser RESTful, la solicitud debe contener toda la información sobre cómo procesarla. Las formas en que puedes hacer esto:

  • Agregue una cookie token csrf con su cliente REST y envíe el mismo token en la entrada oculta con sus formularios. Si el servicio y el cliente están bajo dominios diferentes, debe compartir las credenciales. En el servicio tienes que comparar los 2 tokens, y si son iguales, la solicitud es válida ...

  • Puede agregar la cookie token csrf con su servicio REST y enviar el mismo token con las representaciones de sus recursos (entradas ocultas, etc.). Todo lo demás es lo mismo que el final de la solución anterior. Esta solución está al borde de la RESTfulness. (Está bien hasta que el cliente no llame al servicio para modificar la cookie. Si la cookie es solo http, el cliente no debe saberlo, si no lo está, entonces el cliente debe configurarlo). Puede hacer más solución compleja si agrega tokens diferentes a cada formulario y agrega tiempo de expiración a las cookies. También puede enviar la fecha de vencimiento con los formularios, para que sepa el motivo por el que falla la validación de un token.

  • Puede tener un secreto de usuario (diferente para cada usuario) en el estado del recurso en su servicio. Al construir representaciones, puede generar un token (y tiempo de vencimiento) para cada formulario. Puede generar un hash del token real (y el tiempo de expiración, el método, la url, etc.) y el secreto del usuario, y también enviar ese hash con el formulario. Mantiene el "secreto de usuario" en secreto, por supuesto, por lo que nunca lo envíe con el formulario. Después de eso, si su servicio recibe una solicitud, puede generar nuevamente el hash a partir de los parámetros de solicitud y el secreto de usuario, y compararlos. Si no coinciden, la solicitud no es válida ...

Ninguno de ellos lo protegerá si su cliente REST es javascript inyectable, por lo que debe verificar todo el contenido de su usuario contra entidades HTML y eliminar todas ellas, o usar TextNodes siempre en lugar de innerHTML. También debe protegerse contra la inyección de SQL y la inyección de encabezado HTTP. Nunca use FTP simple para actualizar su sitio. Y así sucesivamente ... Hay muchas maneras de inyectar código malvado en su sitio ...

Casi me olvido de mencionar que las solicitudes GET siempre son para leer por el servicio y por el cliente. Por el servicio esto es obvio, si el cliente establece que cualquier url en el navegador debe dar como resultado una representación de un recurso o múltiples recursos, nunca debe llamar a un método POST / PUT / DELETE en un recurso. Por ejemplo, GET http://my.client.com/resource/delete -> DELETE http://my.api.com/resource es una muy mala solución. Pero esta es una habilidad muy básica si quieres obstaculizar CSRF.


Aquí hay muchas respuestas y problemas con bastantes de ellas.

Cosas que NO debes hacer:

  1. Si necesita leer el token de la sesión desde JavaScript, está haciendo algo terriblemente incorrecto. La cookie del identificador de sesión SIEMPRE debe tener HTTPOnly configurado para que no esté disponible para las secuencias de comandos.

    Esta protección hace que el impacto de XSS se reduzca considerablemente, ya que un atacante ya no podrá obtener un token de sesión de usuario conectado, que para todos los efectos es el equivalente de las credenciales en la aplicación. No quiere un error para dar claves al reino.

  2. El identificador de sesión no se debe escribir en el contenido de la página. Esto es por las mismas razones por las que configura HTTPOnly. Esto significa que su token de sesión no puede ser su identificación de sesión. Necesitan ser valores diferentes.

Cosas que debes hacer:

  1. Sigue la guía de OWASP :

  2. Específicamente, si se trata de una aplicación REST, puede solicitar el doble envío de tokens CSRF :

Simplemente cree algo criptográficamente aleatorio, almacénelo en codificación ASCII Hex o Base64 y agréguelo como una cookie a sus formularios cuando el servidor devuelva la página. En el lado del servidor, asegúrese de que el valor de la cookie coincida con el valor del formulario. Voila, has matado a CSRF, has evitado las indicaciones adicionales para tus usuarios y no te has abierto a más vulnerabilidades.


Definitivamente necesita algún estado en el servidor para autenticar / autorizar. Sin embargo, no es necesario que sea la sesión http, puede almacenarla en un caché distribuido (como memcached) o una base de datos.

Si usa cookies para la autenticación, la solución más fácil es enviar dos veces el valor de la cookie. Antes de enviar el formulario, lea la identificación de la sesión de la cookie, guárdela en un campo oculto y luego envíela. Del lado del servidor, confirme que el valor de la solicitud sea el mismo que el de la sesión (que obtuvo de la cookie). La secuencia de comandos de Evil de otro dominio no podrá leer la identificación de sesión de la cookie, evitando así CSRF.

Este esquema usa un único identificador en toda la sesión.

Si desea más protección, genere un id único por sesión por formulario.

Además, NO generes tokens en JS. Cualquiera puede copiar el código y ejecutarlo desde un dominio diferente para atacar su sitio.


Estoy obteniendo esto bien:

  • Desea protección contra CSRF para los usuarios que inician sesión a través de cookies.
  • Y al mismo tiempo, desea la interfaz RESTful para las solicitudes autenticadas de Basic, OAuth y Digest de las aplicaciones.

Entonces, ¿por qué no verificar si los usuarios están conectados a través de cookies y aplicar CSRF solo entonces ?

No estoy seguro, pero es posible que otro sitio forje cosas como la autenticación básica o los encabezados.

Hasta donde yo sé, CSRF se trata de cookies . La AUTORIZACIÓN RESTful no ocurre con las cookies.


Hay algunos métodos en la Hoja de referencia de prevención de CSRF que pueden ser utilizados por un servicio de descanso. La mitigación de CSRF sin estado más RESTful es usar el origen o revisor HTTP para asegurarse de que las solicitudes se originan en un dominio de confianza.


La ID de forma estática no proporciona protección en absoluto; un atacante puede ir a buscarlo él mismo. Recuerde, el atacante no está obligado a usar JavaScript en el cliente; él puede buscar el ID de forma estática del lado del servidor.

No estoy seguro de entender completamente la defensa propuesta; ¿De dónde GET /usersecret/john_doe ? ¿Es eso parte de la página JavaScript? ¿Es esa la URL literal propuesta? Si es así, supongo que el username no es un secreto, lo que significa que evil.ru puede recuperar los secretos de los usuarios si un navegador o una vulnerabilidad de complemento permite solicitudes GET entre dominios. ¿Por qué no almacenar el secreto de usuario en una cookie al momento de la autenticación en lugar de permitir que cualquiera que pueda hacer un GET entre dominios lo recupere?

Antes de implementar mi propio sistema de autenticación, quería leer "Defensas robustas para la falsificación entre sitios" antes de implementar el sistema CSRF. De hecho, reconsideraría la implementación de mi propio sistema de autenticación.