Aloja datos de usuarios de forma segura en aplicaciones web modernas

David Dworken
David Dworken

Muchas aplicaciones web necesitan mostrar contenido controlado por el usuario. Puede ser tan simple como entregar imágenes subidas por el usuario (por ejemplo, fotos de perfil) o tan complejo como renderizar código HTML controlado por el usuario (por ejemplo, un instructivo de desarrollo web). Esto siempre ha sido difícil de hacer de forma segura, por lo que trabajamos para encontrar soluciones sencillas pero seguras que puedan aplicarse a la mayoría de los tipos de aplicaciones web.

Soluciones clásicas para aislar el contenido que no es de confianza

La solución clásica para entregar contenido controlado por el usuario de forma segura es usar lo que se conoce como dominios de zona de pruebas. La idea básica es que si el dominio principal de tu aplicación es example.com, puedes entregar todo el contenido que no sea de confianza en exampleusercontent.com. Dado que estos dos dominios están entre sitios, el contenido malicioso en exampleusercontent.com no puede afectar a example.com.
Este enfoque se puede usar para entregar de forma segura todo tipo de contenido que no sea de confianza, como imágenes, descargas y HTML. Aunque puede no parecer necesario usar esta opción para imágenes o descargas, hacerlo ayuda a evitar riesgos de analización de contenido, especialmente en navegadores heredados.
Los dominios de zona de pruebas se usan mucho en la industria y han funcionado bien durante mucho tiempo. Sin embargo, tienen dos desventajas principales:

  • A menudo, las aplicaciones necesitan restringir el acceso al contenido a un solo usuario, lo que requiere la implementación de autenticación y autorización. Debido a que los dominios de las zonas de pruebas no comparten cookies con el dominio principal de la aplicación deliberadamente, es muy difícil hacerlo de forma segura. Para admitir la autenticación, los sitios deben basarse en las URLs de capacidad o deben configurar cookies de autenticación diferentes para el dominio de la zona de pruebas. Este segundo método es particularmente problemático en la Web moderna, donde muchos navegadores restringen las cookies entre sitios de forma predeterminada.
  • Si bien el contenido de los usuarios está aislado del sitio principal, no está aislado del contenido de otros usuarios. Esto crea el riesgo de que el contenido malicioso de los usuarios ataque otros datos en el dominio de la zona de pruebas (por ejemplo, mediante la lectura de datos del mismo origen).

También vale la pena señalar que los dominios de las zonas de pruebas ayudan a mitigar los riesgos de suplantación de identidad (phishing), ya que los recursos están claramente segmentados en un dominio aislado.

Soluciones modernas para entregar contenido de los usuarios

Con el tiempo, la Web evolucionó, y ahora existen formas más fáciles y seguras de entregar contenido que no es de confianza. Existen muchos enfoques diferentes, por lo que describiremos dos soluciones que actualmente se utilizan ampliamente en Google.

Enfoque 1: Entrega de contenido para usuarios inactivos

Si un sitio solo necesita mostrar contenido para usuarios inactivos (es decir, contenido que no sea HTML ni JavaScript, como imágenes y descargas), ahora se puede hacer de forma segura sin un dominio de zona de pruebas aislado. Hay dos pasos clave:

  • Siempre configura el encabezado Content-Type con un tipo de MIME conocido que sea compatible con todos los navegadores y que no tenga contenido activo (en caso de dudas, application/octet-stream es una opción segura).
  • Además, establece siempre los siguientes encabezados de respuesta para asegurarte de que el navegador aísle por completo la respuesta.
Encabezado de respuesta Purpose

X-Content-Type-Options: nosniff

Evita los detectores de contenido

Content-Disposition: attachment; filename="download"

Activa una descarga en lugar de renderizar.

Content-Security-Policy: sandbox

Coloca el contenido en la zona de pruebas como si se publicara en un dominio independiente.

Content-Security-Policy: default-src ‘none'

Inhabilita la ejecución de JavaScript (y la inclusión de cualquier subrecurso).

Cross-Origin-Resource-Policy: same-site

Impide que la página se incluya en diferentes sitios

Esta combinación de encabezados garantiza que tu aplicación solo pueda cargar la respuesta como un subrecurso, o que el usuario pueda descargarla como un archivo. Además, los encabezados proporcionan varias capas de protección contra errores del navegador mediante el encabezado de la zona de pruebas de la CSP y la restricción default-src. En general, la configuración descrita anteriormente proporciona un alto nivel de confianza en que las respuestas que se entregan de esta manera no pueden generar vulnerabilidades de inyección o aislamiento.

Defensa en profundidad

Si bien la solución anterior representa una defensa generalmente suficiente contra XSS, existen varias medidas de refuerzo adicionales que puedes aplicar para proporcionar capas adicionales de seguridad:

  • Se estableció un encabezado X-Content-Security-Policy: sandbox para brindar compatibilidad con IE11.
  • Establece un encabezado Content-Security-Policy: frame-ancestors 'none' para bloquear la incorporación del extremo.
  • Puedes hacer lo siguiente para crear una zona de pruebas del contenido de los usuarios en un subdominio aislado:
    • Entrega contenido de los usuarios en un subdominio aislado (p.ej., Google usa dominios como product.usercontent.google.com).
    • Configura Cross-Origin-Opener-Policy: same-origin y Cross-Origin-Embedder-Policy: require-corp para habilitar el aislamiento de origen cruzado.

Enfoque 2: Entrega de contenido de usuarios activos

La entrega segura de contenido activo (por ejemplo, imágenes HTML o SVG) también se puede realizar sin las debilidades del enfoque clásico de dominio de zona de pruebas.
La opción más simple es aprovechar el encabezado Content-Security-Policy: sandbox para indicarle al navegador que aísle la respuesta. Si bien no todos los navegadores web implementan actualmente el aislamiento de procesos para documentos de espacio aislado, es probable que el perfeccionamiento continuo de los modelos de procesos de navegador mejore la separación del contenido de la zona de pruebas de las aplicaciones de incorporación. Si los ataques de SpectreJS y compromiso del procesador están fuera de tu modelo de amenaza, es probable que la solución sea suficiente con la zona de pruebas de la CSP.
En Google, desarrollamos una solución que puede aislar por completo el contenido activo que no es de confianza mediante la modernización del concepto de dominios de zona de pruebas. La idea central es:

  • Crea un nuevo dominio de zona de pruebas que se agregue a la lista de sufijos públicos. Por ejemplo, si agregas exampleusercontent.com al PSL, puedes asegurarte de que foo.exampleusercontent.com y bar.exampleusercontent.com estén entre sitios y, por lo tanto, aislados por completo entre sí.
  • Las URLs que coinciden con *.exampleusercontent.com/shim se enrutan a un archivo estático de corrección de compatibilidad. Este archivo de corrección de compatibilidad contiene un fragmento corto de HTML y JavaScript que escucha al controlador de eventos message y procesa el contenido que recibe.
  • Para usar esto, el producto crea un iframe o una ventana emergente para $RANDOM_VALUE.exampleusercontent.com/shim y usa postMessage para enviar el contenido que no es de confianza a la corrección de compatibilidad para la renderización.
  • El contenido renderizado se transforma en un BLOB y se procesa dentro de un iframe de zona de pruebas.

En comparación con el enfoque clásico de dominio de zona de pruebas, esto garantiza que todo el contenido esté completamente aislado en un sitio único. Además, como la aplicación principal se encarga de recuperar los datos que se van a renderizar, ya no es necesario usar URLs de capability.

Conclusión

En conjunto, estas dos soluciones permiten migrar de los dominios clásicos de la zona de pruebas, como googleusercontent.com, a soluciones más seguras compatibles con el bloqueo de cookies de terceros. En Google, ya migramos muchos productos para usar estas soluciones y planeamos realizar más migraciones para el próximo año.