Protege tus recursos contra ataques web con la función para recuperar metadatos

Evita las filtraciones de información de CSRF, XSSI y orígenes cruzados.

Muchas aplicaciones web son vulnerables a ataques de origen cruzado, como la falsificación de solicitudes entre sitios (CSRF), la inclusión de secuencias de comandos entre sitios (XSSI), los ataques de tiempo, las filtración de información de origen cruzado o los ataques especulativos de canal lateral (Spectre).

Los encabezados de las solicitudes Fetch Metadata le permiten implementar un mecanismo sólido de defensa en profundidad (una política de aislamiento de recursos) para proteger su aplicación contra estos ataques comunes de origen cruzado.

Es común que los recursos expuestos por una aplicación web determinada solo se carguen en la aplicación y no en otros sitios web. En esos casos, implementar una política de aislamiento de recursos basada en encabezados de solicitud de metadatos de recuperación requiere poco esfuerzo y, al mismo tiempo, protege a la aplicación de ataques entre sitios.

Compatibilidad del navegador

Los encabezados de solicitud de recuperación de metadatos son compatibles con todos los motores de navegadores modernos.

Navegadores compatibles

  • Chrome: 76
  • Borde: 79.
  • Firefox: 90.
  • Safari: 16.4.

Origen

Segundo plano

Muchos ataques entre sitios son posibles porque la Web está abierta de forma predeterminada y tu servidor de aplicaciones no puede protegerse fácilmente de la comunicación que se origina en aplicaciones externas. Un ataque de origen cruzado típico es la falsificación de solicitudes entre sitios (CSRF), en la que un atacante atrae a un usuario a un sitio que controla y, luego, envía un formulario al servidor al que el usuario accedió. Dado que el servidor no puede determinar si la solicitud se originó en otro dominio (entre sitios) y el navegador adjunta cookies automáticamente a las solicitudes entre sitios, el servidor ejecutará la acción solicitada por el atacante en nombre del usuario.

Otros ataques entre sitios, como la inclusión de secuencias de comandos entre sitios (XSSI) o las filtraciones de información de origen cruzado, son de naturaleza similar a la CSRF y dependen de cargar recursos desde una aplicación víctima en un documento controlado por el atacante y filtrar información sobre las aplicaciones víctimas. Dado que las aplicaciones no pueden distinguir fácilmente las solicitudes de confianza de las no confiables, no pueden descartar el tráfico malicioso entre sitios.

Presentamos los metadatos de recuperación

Los encabezados de la solicitud Fetch Metadata son una nueva función de seguridad para la plataforma web diseñada para ayudar a los servidores a defenderse de ataques de origen cruzado. Cuando proporcionan información sobre el contexto de una solicitud HTTP en un conjunto de encabezados Sec-Fetch-*, permiten que el servidor que responde aplique políticas de seguridad antes de procesar la solicitud. Esto permite que los desarrolladores decidan si aceptar o rechazar una solicitud según la forma en que se realizó y el contexto en el que se usará, lo que permite responder solo a las solicitudes legítimas que realiza su propia aplicación.

Same-Origin
Las solicitudes que se originen en sitios entregados por tu propio servidor (mismo origen) seguirán funcionando. Una solicitud de recuperación de https://sitio.ejemplo para el recurso https://sitio.ejemplo/foo.json en JavaScript hace que el navegador envíe el encabezado de solicitud HTTP "Sec Fetch-Site: same-origin".
Entre sitios
El servidor puede rechazar las solicitudes maliciosas entre sitios debido al contexto adicional de la solicitud HTTP que proporcionan los encabezados Sec-Fetch-*. Una imagen en https://evil.example que estableció el atributo src de un elemento img en "https://site.example/foo.json" hace que el navegador envíe el encabezado de solicitud HTTP "Sec-Fetch-Site: cross-site".

Sec-Fetch-Site

Navegadores compatibles

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4.

Origen

Sec-Fetch-Site le indica al servidor qué sitio envió la solicitud. El navegador establece este valor en uno de los siguientes:

  • same-origin, si la solicitud fue realizada por tu propia aplicación (p.ej., site.example)
  • same-site, si la solicitud proviene de un subdominio de tu sitio (p.ej., bar.site.example)
  • none, si la solicitud se debió explícitamente a la interacción de un usuario con el usuario-agente (p.ej., si hizo clic en un favorito)
  • cross-site, si otro sitio web envió la solicitud (p.ej., evil.example)

Sec-Fetch-Mode

Navegadores compatibles

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4.

Origen

Sec-Fetch-Mode indica el modo de la solicitud. Esto corresponde aproximadamente al tipo de solicitud y te permite distinguir las cargas de recursos de las solicitudes de navegación. Por ejemplo, un destino de navigate indica una solicitud de navegación de nivel superior, mientras que no-cors indica solicitudes de recursos, como cargar una imagen.

Sec-Fetch-Dest

Navegadores compatibles

  • Chrome: 80.
  • Edge: 80.
  • Firefox: 90.
  • Safari: 16.4.

Origen

Sec-Fetch-Dest expone el destino de una solicitud (p.ej., si una etiqueta script o img hizo que el navegador solicite un recurso).

Cómo usar la recuperación de metadatos para brindar protección contra ataques de origen cruzado

La información adicional que proporcionan estos encabezados de solicitud es bastante simple, pero el contexto adicional te permite crear una lógica de seguridad potente en el lado del servidor, también conocida como política de aislamiento de recursos, con solo unas pocas líneas de código.

Implementa una política de aislamiento de recursos

Una política de aislamiento de recursos evita que los sitios web externos soliciten tus recursos. El bloqueo de ese tráfico mitiga las vulnerabilidades web comunes entre sitios, como CSRF, XSSI, ataques de sincronización y filtraciones de información de origen cruzado. Esta política se puede habilitar para todos los extremos de tu aplicación y permitirá todas las solicitudes de recursos que provengan de tu aplicación y las navegaciones directas (a través de una solicitud GET HTTP). Los extremos que deberían cargarse en un contexto de varios sitios (p.ej., extremos cargados con CORS) pueden inhabilitarse de esta lógica.

Paso 1: Permite las solicitudes de navegadores que no envían metadatos de recuperación

Como no todos los navegadores admiten la recuperación de metadatos, debes permitir las solicitudes que no establecen encabezados Sec-Fetch-* verificando la presencia de sec-fetch-site.

if not req['sec-fetch-site']:
  return True  # Allow this request

Paso 2: Permite solicitudes iniciadas por el mismo sitio y por el navegador

Se permitirán todas las solicitudes que no se originen en un contexto de origen cruzado (como evil.example). En particular, estas son solicitudes que hacen lo siguiente:

  • Provengan de tu propia aplicación (p. ej., una solicitud del mismo origen en la que site.example solicite site.example/foo.json siempre se permitirá).
  • Provengan de tus subdominios.
  • Son causados explícitamente por la interacción de un usuario con el usuario-agente (p. ej., navegación directa o hacer clic en un favorito, etcétera).
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
  return True  # Allow this request

Paso 3: Permite la navegación simple de nivel superior y el iframe

Para asegurarte de que tu sitio se pueda vincular desde otros sitios, debes permitir la navegación de nivel superior simple (HTTP GET).

if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
  # <object> and <embed> send navigation requests, which we disallow.
  and req['sec-fetch-dest'] not in ('object', 'embed'):
    return True  # Allow this request

Paso 4: Inhabilita los extremos diseñados para entregar tráfico entre sitios (opcional)

En algunos casos, tu aplicación puede proporcionar recursos que se cargan en varios sitios. Estos recursos deben estar exentos por ruta de acceso o por extremo. Estos son algunos ejemplos de esos extremos:

  • Extremos a los que se debe acceder de origen cruzado: Si tu aplicación entrega extremos que tienen habilitada la CORS, debes inhabilitarlos de forma explícita del aislamiento de recursos para asegurarte de que aún sea posible realizar solicitudes entre sitios a estos extremos.
  • Recursos públicos (por ejemplo, imágenes, estilos, etc.): También se pueden eximir todos los recursos públicos y no autenticados que deban ser cargables de origen cruzado desde otros sitios.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
  return True

Paso 5: Rechaza todas las demás solicitudes que sean entre sitios y no de navegación

Esta política de aislamiento de recursos rechazará cualquier otra solicitud entre sitios y, por lo tanto, protegerá tu aplicación de ataques comunes entre sitios.

Ejemplo: En el siguiente código, se muestra una implementación completa de una política de aislamiento de recursos sólida en el servidor o como un middleware para denegar solicitudes de recursos potencialmente maliciosos entre sitios, a la vez que permite solicitudes de navegación simples:

# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
  # Allow requests from browsers which don't send Fetch Metadata
  if not req['sec-fetch-site']:
    return True

  # Allow same-site and browser-initiated requests
  if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
    return True

  # Allow simple top-level navigations except <object> and <embed>
  if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
    and req['sec-fetch-dest'] not in ('object', 'embed'):
      return True

  # [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
  if req.path in ('/my_CORS_endpoint', '/favicon.png'):
    return True

  # Reject all other requests that are cross-site and not navigational
  return False

Implementa una política de aislamiento de recursos

  1. Instala un módulo como el fragmento de código anterior para registrar y supervisar el comportamiento de tu sitio y asegúrate de que las restricciones no afecten el tráfico legítimo.
  2. Para corregir los posibles incumplimientos, exime los extremos de origen cruzado legítimos.
  3. Para aplicar la política, descarta las solicitudes que no cumplan con ella.

Identificación y solución de incumplimientos de política

Te recomendamos que pruebes tu política sin efectos secundarios. Para ello, primero habilítala en el modo de informes en tu código del servidor. Como alternativa, puedes implementar esta lógica en middleware o en un proxy inverso que registre cualquier incumplimiento que tu política pueda producir cuando se aplique al tráfico de producción.

Según nuestra experiencia en el lanzamiento de una Política de aislamiento de recursos para la recuperación de metadatos en Google, la mayoría de las aplicaciones son compatibles de forma predeterminada con dicha política y rara vez requieren la exención de endpoints para permitir el tráfico entre sitios.

Aplicación de una política de aislamiento de recursos

Después de que hayas verificado que tu política no afecta el tráfico de producción legítimo, estarás listo para aplicar restricciones y garantizar que otros sitios no puedan solicitar tus recursos y proteger a tus usuarios de ataques entre sitios.

Lecturas adicionales