Prevención de CORS y CSRF para una API basada en REST

4

Actualmente estoy tratando de ver cómo prevenir el CSRF.

Mi primera solución fue usar un token que se sugiere en todas partes. Eso, por supuesto, solucionaría este problema:

<img src="http://api.example.com/me/delete">

Peroloquenopuedoentendereseso.

GEThttp://api.example.com/me/delete

Dehecho,fallaráporqueuntokenválidonovinojuntoconesasolicitud,peroloqueimpidequeunatacantehagaloanterioryensulugarsimplementehacelosiguiente

GEThttp://api.example.com/me/token/generate//parsetheresponseGEThttp://api.example.com/me/delete?token=...

Sehapasadountokenválidoalolargodelasolicitud,miusuarioahoraestáeliminado...

MiAPIRESTpermitequeserecibacualquiersolicitud.

header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);

La razón por la que "necesito" es que no solo uso la API REST en el propio dominio a través de formularios y JavaScript. Pero estoy haciendo solicitudes usando cURL en C ++.

Si los tokens en este caso no son una solución "segura", ¿cuál sería / podría ser una solución más segura / mejor?

Además, ¿qué hace algo como Spotify, mientras que ambos tienen su "API web" y el software de música en sí?

También, y sé que esto es inverosímil, pero ¿es posible permitir que cualquier acceso a mi API tenga una autenticación por origen?

Por lo tanto, si enlace está "conectado a" la API, no significa que enlace es (o más cuando solicite el uso de cURL).

Sé que esto es inverosímil, ya que la "solución" sería verificar el encabezado de origen, pero se puede falsificar.

    
pregunta Vallentin 08.06.2015 - 15:52
fuente

3 respuestas

7

La Política del mismo origen normalmente evitaría que se produjera su escenario:

GET http://api.example.com/me/token/generate
// parse the response

La respuesta no se puede analizar a través de un dominio de terceros que realiza solicitudes a su dominio. El navegador normalmente lo bloqueará debido al SOP.

Digo normalmente porque también has agregado el siguiente encabezado de respuesta para relajar las reglas de Same Origin:

header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);

Bajo el siguiente error:

  

La razón por la que "necesito" es que no solo estoy usando la API REST en   El propio dominio a través de formularios y JavaScript. Pero estoy haciendo peticiones   usando cURL en C ++.

Este encabezado no tiene ninguna relación con cURL. El encabezado es analizado solo por los navegadores, implementando el SOP. No hace nada para evitar que lleguen solicitudes directas para un cliente web.

Solución

En su dominio api.example.com , solo permita que el front-end realice solicitudes a través del navegador del usuario:

Access-Control-Allow-Origin: example.com

En su sitio example.com , envíe el siguiente encabezado con todas las solicitudes API AJAX:

X-Requested-With: XMLHttpRequest

Consulte esta respuesta para obtener información sobre esto . En pocas palabras, este encabezado no se puede enviar entre dominios sin que CORS esté habilitado.

Verifique en su backend API que este encabezado esté presente cuando se reciba una solicitud. Si no lo es, entonces es un ataque CSRF.

En sus solicitudes del lado del servidor usando cURL, simplemente agregue el encabezado manualmente. por ejemplo

X-Requested-With: cURL

Cuando esté verificando que está presente, estas solicitudes tendrán éxito.

Por último, agrega alguna autenticación usando cookies. Los usuarios registrados en el sitio web deben tener un ticket de autenticación que se puede enviar en una cookie, y usted debe tener uno para sus solicitudes de backend cURL para usar. Esto asegurará que nadie pueda usar su API sin permiso. Es posible que desee restringir las acciones que los usuarios web pueden realizar utilizando los niveles de autorización, ya que de lo contrario, podrían intentar ejecutar maliciosamente una función que solo su herramienta de servidor cURL debería hacer.

    
respondido por el SilverlightFox 27.09.2015 - 12:48
fuente
1

Espero haber entendido tu pregunta.

En cuanto a la primera parte, Normalmente, dado que el atacante estará en un origen diferente de su servidor, el navegador no permitirá que lea la respuesta , lo que le impide "analizar la respuesta" y enviarla. El token en una solicitud posterior. Pero ha permitido explícitamente todos los orígenes que hacen que esta protección sea inútil.

Además, el token generado obviamente debe requerir autenticación de algún tipo, en donde el token del Usuario A no será válido para el B, por lo que incluso si envía el token manualmente, no será válido.

Segunda parte, Si tuvieras algún tipo de mecanismo de token implementado correctamente, sin importar de dónde provenga la solicitud, el token evitaría la actividad maliciosa.

En cuanto a la tercera parte, si entendí tu pregunta correctamente: En lo que respecta a trabajar con un navegador, CORS no permite configurar el origen mediante javascript o cualquier código del lado del cliente . Por lo tanto, en el caso de un ataque CSRF que requiera un cierto valor para Origin, el atacante no puede falsificar ese valor usando Javascript.

Espero que ayude.

    
respondido por el Aatif Shahdad 08.06.2015 - 18:19
fuente
1

Considerando el escenario de la pregunta original, creo que el token OAuth / JWT es el enfoque recomendado. Para esos escenarios, desea permitir que otros orígenes tengan acceso a sus API, pero solo permite aquellas solicitudes que están autorizadas. Aquí es donde un token JWT proporciona este nivel de seguridad a medida que se agregan reclamos al token y usted puede agregar los filtros de autorización según esos reclamos.

Para aquellos que buscan permitir solo las mismas solicitudes de origen, ninguna autenticación de usuario y evitar CSRF, un token anti-falsificación con un filtro de validación puede hacer el truco. Un caso típico podría ser un formulario de contacto. Para obtener más información sobre esto, eche un vistazo a este ejemplo con una aplicación angularjs:

enlace

espero que ayude.

    
respondido por el ozkary 10.03.2016 - 18:55
fuente

Lea otras preguntas en las etiquetas