¿Qué son los ataques CORS y cómo evitarlos?

Las aplicaciones web modernas de hoy dependen en gran medida de JavaScript para ser dinámicas y garantizar la mejor experiencia para los usuarios finales. Proporcionar contenido y datos a los usuarios a menudo requiere interacciones con otras aplicaciones web, que incluyen solicitudes de dominio cruzado y un paso de configuración adicional en el lado de la aplicación conocido como política de intercambio de recursos de origen cruzado (CORS).

Los ataques de intercambio de recursos de origen cruzado (CORS) son posibles a través de configuraciones incorrectas del servidor web. En este artículo, veremos qué son los ataques CORS, cómo funcionan y qué puedes hacer para evitarlos.

Pero antes de sumergirnos en CORS en sí, debemos comprender un poco sobre otra política de seguridad importante del servidor web: la política del mismo origen (SOP).

Política del mismo origen

La mayoría de los servidores web están configurados con una política del mismo origen (SOP). Lo que hace SOP es restringir los orígenes desde los cuales los scripts pueden acceder a otros orígenes. Si esa última oración no tiene sentido para ti, no te preocupes, lo tendrá.

Un origen consta de:

  • un esquema de URI
  • un dominio
  • un número de puerto

Se parece a esto:

http://regular-website.com/regular-stuff/stuff.hmtl

En el ejemplo anterior, el esquema de URI es HTTP, el dominio es regular-website.com y el puerto está implícito en 80 porque nuestro esquema de URI es HTTP, que implícitamente usa el puerto 80.

Un origen es simplemente una ubicación específica en un servidor web a la que se puede acceder mediante un esquema de URI, dominio y número de puerto. Tanto el servidor web solicitante como el servidor web solicitado tienen origen.

Con un SOP adecuado en su lugar, el servidor web rechazará cualquier origen (es decir, el esquema de URI, dominio y número de puerto de otro servidor web) que solicite acceso a http://regular-website.com/regular-stuff/stuff utilizando un Esquema de URI, dominio o número de puerto.

La política del mismo origen es fundamental porque, cuando un navegador realiza una solicitud de un origen a otro, las cookies de sesión se pueden enviar junto con la solicitud para generar la respuesta dentro de la sesión del usuario y proporcionar datos potencialmente sensibles y específicos del usuario. Las cookies de sesión se utilizan para mantenerte conectado a un sitio web en visitas posteriores, pero también pueden ser utilizadas por un atacante para evitar el proceso de inicio de sesión del sitio.

Sin un SOP adecuado, si iniciaras sesión en tu sitio web bancario, cualquier otra pestaña abierta en tu navegador (si contenía recursos maliciosos) podría acceder a tu sesión bancaria en línea. Si inicias sesión en tu correo electrónico, podrían leer tus correos electrónicos. Si tuvieras un chat privado en una aplicación de mensajería, podrían leer tus conversaciones privadas.

Eso es lo que es SOP, en pocas palabras. Funciona. Pero puede resultar algo restrictivo. Después de todo, hoy en día, hay muchos sitios web / servicios en línea que interactúan entre sí y requieren acceso de origen cruzado.

Ahí es donde entra CORS.

¿Qué es CORS?

CORS es un estándar de seguridad implementado por los navegadores que permite que los scripts que se ejecutan en los navegadores accedan a recursos ubicados fuera del dominio del navegador.

El protocolo CORS consta de un conjunto de encabezados que indica si una respuesta se puede compartir de origen cruzado. Para las solicitudes que son más complicadas de lo que es posible con el elemento de formulario de HTML, se realiza una solicitud de verificación previa CORS, para garantizar que la URL actual de la solicitud sea compatible con el protocolo CORS.

El intercambio de recursos de origen cruzado (CORS) puede entenderse como una relajación controlada de la política del mismo origen. CORS proporciona una forma controlada de compartir recursos de origen cruzado.

El protocolo CORS funciona con encabezados HTTP específicos que especifican qué orígenes web son confiables y sus propiedades asociadas, como si se permite el acceso autenticado. Estos parámetros se expresan en intercambios de encabezados HTTP entre un navegador y el sitio web de origen cruzado al que intenta acceder.

Así es como se ve un encabezado típico con el parámetro de origen especificado (en negrita):

GET /resources/public-data/ HTTP/1.1
Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive
Origin: https://foo.example

En el ejemplo anterior, el esquema de URI es HTTPS, el dominio es foo.example y el número de puerto es 443 (como lo implica HTTPS).

Cuando este encabezado se transmite al sitio web, el sitio web tendrá que hacer una llamada sobre si permite o no la solicitud de origen cruzado. La concesión o no de la solicitud depende de la configuración de CORS del sitio web receptor. Y es esta configuración la que abre la puerta a los ataques CORS.

Si CORS está mal configurado en el servidor web y ‘foo.example’ es un sitio malicioso, aceptará la solicitud y puede ser víctima de un ataque CORS. Pero esa es solo la mitad de la historia.

Terminología

Antes de continuar, definamos algunos términos de uso frecuente como navegadores, servidores, orígenes, orígenes cruzados. Luego usaremos estos términos de manera consistente a lo largo de este artículo.

¿Qué es un origen?

Un origen en el contexto de CORS consta de tres elementos:

  • Esquema URI, por ejemplo http://ohttps://
  • Nombre de host como www.xyz.com
  • Número de puerto como 8000o 80(puerto HTTP predeterminado)

Consideramos que dos URL tienen el mismo origen solo si los tres elementos coinciden.

Servidor de origen y servidor de origen cruzado

Los términos servidor de origen y servidor de origen cruzado no son términos CORS. Pero usaremos estos términos para referirnos al servidor que aloja la aplicación de origen y al servidor al que el navegador enviará la solicitud CORS.

Los siguientes pasos ocurren cuando un usuario escribe una URL: http://www.example.com/index.html en el navegador:

  • El navegador envía la solicitud a un servidor en un dominio llamado www.example.com. A este servidor lo llamaremos “servidor de origen ” que aloja la página nombrada index.html.
  • El servidor de origen devuelve la página nombrada index.html como respuesta al navegador.
  • El servidor de origen también aloja otros recursos como la movies.jsonAPI en este ejemplo.
  • El navegador también puede obtener recursos de un servidor en un dominio diferente como www.xyz.com. A este servidor lo llamaremos «servidor de origen cruzado».

El servidor de origen es el servidor desde el que se obtiene la página web y el servidor de origen cruzado es cualquier servidor que sea diferente del servidor de origen.

Mismo origen frente a origen cruzado

Como se indicó anteriormente, la Política del mismo origen (SOP) es una política de seguridad predeterminada implementada por los navegadores. El SOP permite que el navegador cargue recursos solo desde el servidor de origen.

En ausencia de la Política del mismo origen, cualquier script descargado de servidores de origen cruzado podrá acceder al modelo de objeto de documento (DOM) de nuestro sitio web y permitirle acceder a datos potencialmente confidenciales o realizar acciones maliciosas sin requerir el consentimiento del usuario.

Tipos de configuraciones incorrectas de CORS

Es la mitad de la historia porque hay dos tipos principales de configuraciones incorrectas de CORS que pueden hacer que un servidor web sea vulnerable a los ataques de CORS, y necesita ambos para lograrlo.

  • Access-Control-Allow-Origin (ACAO): esto permite la comunicación bidireccional con sitios web de terceros. Una configuración incorrecta de Access-Control-Allow-Origin (ACAO) puede explotarse para modificar o canalizar datos confidenciales, como nombres de usuario y contraseñas.
  • Access-Control-Allow-Credentials (ACAC): esto permite que los sitios web de terceros ejecuten acciones privilegiadas que solo el usuario autenticado genuino debería poder realizar. Algunos ejemplos serían cambiar su contraseña o su información de contacto.

Ambos parámetros funcionan en conjunto dentro de la configuración CORS del servidor web.

Se reducen a dos preguntas que el servidor web debe responder:

  • ¿El servidor web acepta la solicitud del origen indicado?
  • Si es así, ¿también proporciona credenciales para ejecutar acciones privilegiadas?

La primera pregunta corresponde a la política Access-Control-Allow-Origin y la segunda pregunta corresponde a la política Access-Control-Allow-Credentials.

Veamos las diferentes formas en que los servidores web pueden configurar su política Access-Control-Allow-Origin:

Política de acceso-control-permiso-origen

Permitir todos los orígenes (*)

Esto permite el acceso desde todos los orígenes. Tan pronto como se reciba una solicitud de origen cruzado, se permitirá. El encabezado de respuesta se vería así:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://website.com

Esto se conoce como reflexión de origen porque el servidor web simplemente «refleja» el origen que se encuentra en el encabezado de la solicitud en el encabezado de respuesta. El servidor web utiliza un comodín (*) para aceptar todas las solicitudes de origen cruzado.

Ten en cuenta que esto no es necesariamente desastroso desde una perspectiva de seguridad. Esta configuración es utilizada por muchos sitios web públicos o puntos finales de API que están destinados a ser de acceso público.

Permitir subdominios (* .website.com)

Configurar la política ACAO para permitir subdominios permitirá solicitudes de origen cruzado desde cualquier subdominio del dominio definido. Si llega una solicitud válida, se permitirá. El encabezado de respuesta se vería así:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://subdomain.website.com

Comodín anterior / posterior al dominio (* sitio web.com / sitio web.com. *)

Establecer su política de ACAO para aceptar solicitudes de comodines anteriores o posteriores de un dominio determinado aceptaría solicitudes de origen cruzado de evilwebsite.com o website.com.evilsite.com. Los encabezados de respuesta se verían así:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://evilwebsite.com

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://website.com.evilsite.com

Nulo permitido (nulo)

Muchos lenguajes de desarrollo representan encabezados inexistentes con el valor «nulo». Establecer tu política ACAO en nula significa que el servidor web aceptará solicitudes de origen cruzado desde el origen «nulo». Esto a menudo se implementa en entornos de desarrollo web internos (intranet). El encabezado de respuesta se vería así:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: null

Política de acceso-control-permiso-credenciales

La política Access-Control-Allow-Credentials se establece con un valor de verdadero o falso. Y es realmente esta configuración la que, cuando se establece en «true», habilita la mayoría de los ataques CORS. El encabezado de respuesta se vería así:

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true

Sin este encabezado, el navegador de la víctima no enviará sus cookies, por lo que el atacante solo puede acceder a contenido no autenticado, al que podría acceder fácilmente simplemente navegando por el sitio web de destino.

La gravedad de la infracción abierta por la política Access-Control-Allow-Credentials depende de la política Access-Control-Allow-Origin. Una política de ACAO establecida en * (Permitir todos los orígenes) con una política de ACAC establecida en «verdadero» abre una infracción mayor que una política de ACAO establecida en «Permitir subdominios» con una política de ACAC establecida en «verdadero».

Ejemplo de ataque CORS

Así es como podría verse un ataque CORS:

  • La víctima visita evilwebsite.com mientras está autenticada en goodwebsite.com.
  • evilwebsite.com descarga un script malicioso diseñado para interactuar con goodwebsite.com en la máquina de la víctima.
  • La víctima ejecuta sin saberlo el script malicioso y el script emite una solicitud de origen cruzado a goodwebsite.com. En este ejemplo, supongamos que la solicitud está diseñada para obtener las credenciales necesarias para realizar una acción privilegiada, como revelar la contraseña del usuario.
  • goodwebsite.com recibe la solicitud de origen cruzado de la víctima y el encabezado CORS.
  • El servidor web verificará el encabezado CORS para determinar si enviar o no los datos a goodwebsite.com. En este ejemplo, asumimos que CORS está permitido con autenticación (Access-Control-Allow-Credentials: true).
  • La solicitud se valida y los datos se envían desde el navegador de la víctima a evilwebsite.com.

Este es el peor de los casos, donde todo está abierto de par en par. Pero todavía ejemplifica cómo se ve un ataque CORS. Y este escenario del peor de los casos es bastante común. De hecho, en 2016, se descubrió que Facebook era vulnerable a un ataque CORS de este tipo.

Cómo prevenir ataques basados ​​en CORS

Son principalmente las configuraciones incorrectas del servidor web las que habilitan las vulnerabilidades de CORS. La solución es evitar que surjan vulnerabilidades en primer lugar configurando correctamente las políticas CORS de tu servidor web. A continuación, se ofrecen algunos consejos sencillos para prevenir ataques CORS.

1. Especifica los orígenes permitidos

Si un recurso web contiene información confidencial, los orígenes permitidos deben especificarse en su totalidad en el encabezado Access-Control-Allow-Origin (es decir, sin comodines).

2. Permitir solo sitios de confianza

Si bien esto puede parecer obvio, especialmente teniendo en cuenta el consejo anterior, los orígenes especificados en el encabezado Access-Control-Allow-Origin deben ser exclusivamente sitios de confianza. Lo que quiero decir es que debes evitar reflejar dinámicamente los orígenes de los encabezados de solicitud entre dominios sin validación, a menos que el sitio web sea un sitio público que no requiera ningún tipo de autenticación para el acceso, como un punto final de API.

3. No incluyas «nulo» en la lista blanca

Debes evitar usar el encabezado Access-Control-Allow-Origin: null. Si bien las llamadas a recursos entre dominios desde documentos internos y solicitudes de espacio aislado pueden especificar el origen «nulo», debes tratar las solicitudes internas de origen cruzado de la misma manera que las solicitudes externas de origen cruzado. Debes definir correctamente tus encabezados CORS.

4. Implementar políticas de seguridad adecuadas en el lado del servidor

No creas que configurar correctamente tus encabezados CORS es suficiente para proteger tu servidor web. Es una de las piezas, pero no es completa. CORS define los comportamientos del navegador y nunca reemplaza la protección de datos confidenciales del lado del servidor. Debes continuar protegiendo los datos confidenciales, como la autenticación y la administración de sesiones, además de CORS correctamente configurado.

Como usuario, básicamente deseas estar un paso por delante de las estafas de phishing y los sitios web y descargas maliciosos para minimizar las posibilidades de ser víctima de un ataque CORS. Los siguientes consejos de sentido común pueden ayudar.

Estos pasos son similares para muchos ataques en línea, como evitar antivirus falsos, por lo que generalmente son buenas prácticas a seguir.

  • Utiliza un cortafuegos: todos los principales sistemas operativos tienen un cortafuegos entrante integrado y todos los enrutadores comerciales del mercado tienen un cortafuegos NAT incorporado. Asegúrate de habilitarlos, ya que pueden protegerte en caso de que hagas clic en un enlace malicioso.
  • Solo compra software antivirus genuino y bien revisado de proveedores legítimos y configúralo para ejecutar análisis frecuentes a intervalos regulares.
  • Nunca hagas clic en las ventanas emergentes. Nunca se sabe a dónde te llevarán a continuación.
  • Si tu navegador muestra una advertencia sobre un sitio web al que estás intentando acceder, debes prestar atención y obtener la información que necesitas en otro lugar.
  • No abras archivos adjuntos en correos electrónicos a menos que sepas exactamente quién envió el archivo adjunto y qué es.
  • No hagas clic en los enlaces (URL) en los correos electrónicos a menos que sepas exactamente quién envió la URL y a dónde se vincula. E incluso entonces, inspecciona el enlace con cuidado. ¿Es un enlace HTTP o HTTPS? La mayoría de los sitios legítimos utilizan HTTPS en la actualidad. ¿El enlace contiene errores ortográficos (faceboook en lugar de facebook)? Si puedes llegar al destino sin usar el enlace, hazlo.

La fuga de información es un caso básico de explotación de las vulnerabilidades de CORS. Sin embargo, los atacantes a menudo aprovechan estos problemas para realizar escenarios de ataque avanzados, lo que puede llevar a la toma de control de las cuentas de usuario de la aplicación o la ejecución de modificaciones arbitrarias en la aplicación de destino en nombre del usuario víctima.