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

Evita CSRF, XSSI y fugas de información entre orígenes.

¿Por qué debería importarte aislar tus recursos web?

Muchas aplicaciones web son vulnerables a ataques entre orígenes, como la falsificación de solicitudes entre sitios (CSRF), la inclusión de secuencias de comandos entre sitios (XSSI), los ataques de sincronización, las filtraciones de información entre orígenes o los ataques de canal lateral de ejecución especulativa (Spectre).

Los encabezados de solicitud de obtener metadatos te permiten implementar un mecanismo sólido de defensa en profundidad (una política de aislamiento de recursos) para proteger tu aplicación contra estos ataques comunes entre orígenes.

Es común que la aplicación web en cuestión sea la única que cargue los recursos que expone, y no 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 navegador modernos.

Navegadores compatibles

  • Chrome: 76.
  • Edge: 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 proviene de 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ó. Como el servidor no puede saber 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 que solicitó 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 entre orígenes, son similares en naturaleza a la CSRF y dependen de la carga de recursos de una aplicación víctima en un documento controlado por el atacante y de la filtración de 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 solicitud de metadatos de recuperación son una nueva función de seguridad de la plataforma web diseñada para ayudar a los servidores a defenderse contra los 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 que publique 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 entre sitios maliciosas debido al contexto adicional en 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 la realizó tu propia aplicación (p.ej., site.example)
  • same-site, si la solicitud la realizó un subdominio de tu sitio (p.ej., bar.site.example)
  • none, si la solicitud se produjo explícitamente por la interacción de un usuario con el usuario-agente (p.ej., hacer 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 solicitara un recurso).

Cómo usar los metadatos de recuperación para protegerte 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 servidor, también conocida como política de aislamiento de recursos, con solo unas pocas líneas de código.

Cómo implementar 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 propia aplicación, así como las navegaciones directas (a través de una solicitud HTTP GET). Los extremos que se supone que se cargan en un contexto entre sitios (p.ej., extremos cargados con CORS) pueden inhabilitar 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 las solicitudes del mismo sitio y las que inicia 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 y el enmarcado de iFrame de nivel superior simples

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 que se diseñaron para publicar 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 (p. ej., imágenes, estilos, etcétera): También se pueden eximir los recursos públicos y no autenticados que se deban poder cargar 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, de esta manera, protegerá tu aplicación de los 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.

Identifica y corrige 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 el middleware o en un proxy inverso que registre cualquier incumplimiento que pueda producir tu política cuando se aplique al tráfico de producción.

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

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

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

Lecturas adicionales