Chrome 67 para computadoras de escritorio tiene una nueva función llamada Aislamiento de sitios habilitada de forma predeterminada. En este artículo, se explica en qué consiste el aislamiento de sitios, por qué es necesario y por qué los desarrolladores web deberían conocerlo.
¿Qué es el aislamiento de sitios?
Internet sirve para mirar videos de gatos y administrar billeteras de criptomonedas, entre otras cosas, pero no querrás que fluffycats.example
tenga acceso a tus preciadas criptomonedas. Por suerte, los sitios web suelen no poder acceder a los datos de los demás dentro del navegador gracias a la Política de origen. Sin embargo, los sitios web maliciosos pueden intentar eludir esta política para atacar otros sitios web y, en ocasiones, se encuentran errores de seguridad en el código del navegador que aplica la política de mismo origen. El equipo de Chrome se esfuerza por corregir estos errores lo más rápido posible.
El aislamiento de sitios es una función de seguridad de Chrome que ofrece una línea de defensa adicional para reducir las probabilidades de que estos ataques tengan éxito. Garantiza que las páginas de diferentes sitios web siempre se coloquen en procesos diferentes, cada uno de los cuales se ejecuta en una zona de pruebas que limita lo que el proceso puede hacer. También impide que el proceso reciba ciertos tipos de datos sensibles de otros sitios. Como resultado, con el aislamiento de sitios, es mucho más difícil para un sitio web malicioso usar ataques especulativos de canal lateral, como Spectre, para robar datos de otros sitios. A medida que el equipo de Chrome termine de implementar medidas adicionales, el aislamiento de sitios también ayudará incluso cuando la página de un atacante pueda incumplir algunas de las reglas en su propio proceso.
El aislamiento de sitios dificulta de manera eficaz que los sitios web no confiables accedan a información de tus cuentas en otros sitios web o la roben. Ofrece protección adicional contra varios tipos de errores de seguridad, como los ataques de canal lateral recientes de Meltdown y Spectre.
Para obtener más detalles sobre el aislamiento de sitios, consulta nuestro artículo en el blog de Google Security.
Bloqueo de lectura de origen cruzado
Incluso cuando todas las páginas entre sitios se colocan en procesos separados, las páginas aún pueden solicitar, de forma legítima, algunos recursos secundarios entre sitios, como imágenes y JavaScript. Una página web maliciosa podría usar un elemento <img>
para cargar un archivo JSON con datos sensibles, como tu saldo bancario:
<img src="https://your-bank.example/balance.json" />
<!-- Note: the attacker refused to add an `alt` attribute, for extra evil points. -->
Sin el aislamiento de sitios, el contenido del archivo JSON llegaría a la memoria del proceso del renderizador, en cuyo punto el renderizador nota que no es un formato de imagen válido y no renderiza una imagen. Sin embargo, el atacante podría aprovechar una vulnerabilidad como Spectre para leer potencialmente ese fragmento de memoria.
En lugar de usar <img>
, el atacante también podría usar <script>
para confirmar los datos sensibles en la memoria:
<script src="https://your-bank.example/balance.json"></script>
El bloqueo de lectura de origen cruzado, o CORB, es una nueva función de seguridad que evita que el contenido de balance.json
ingrese a la memoria del proceso del renderizador según su tipo de MIME.
Veamos cómo funciona CORB. Un sitio web puede solicitar dos tipos de recursos a un servidor:
- Recursos de datos, como documentos HTML, XML o JSON
- Recursos multimedia, como imágenes, JavaScript, CSS o fuentes
Un sitio web puede recibir recursos de datos de su propio origen o de otros orígenes con encabezados CORS permisivos, como Access-Control-Allow-Origin: *
. Por otro lado, los recursos multimedia se pueden incluir desde cualquier origen, incluso sin encabezados CORS permisivos.
CORB evita que el proceso del renderizador reciba un recurso de datos de origen cruzado (es decir, HTML, XML o JSON) en los siguientes casos:
- el recurso tiene un encabezado
X-Content-Type-Options: nosniff
- El CORS no permite explícitamente el acceso al recurso.
Si el recurso de datos de origen cruzado no tiene configurado el encabezado X-Content-Type-Options: nosniff
, CORB intenta detectar el cuerpo de la respuesta para determinar si es HTML, XML o JSON. Esto es necesario porque algunos servidores web están mal configurados y entregan imágenes como text/html
, por ejemplo.
Los recursos de datos que bloquea la política de CORB se presentan al proceso como vacíos, aunque la solicitud aún se realiza en segundo plano. Como resultado, a una página web maliciosa le cuesta extraer datos entre sitios en su proceso de robo.
Para obtener una seguridad óptima y beneficiarte de CORB, te recomendamos lo siguiente:
- Marca las respuestas con el encabezado
Content-Type
correcto. (por ejemplo, los recursos HTML deben entregarse comotext/html
, los recursos JSON con un tipo MIME JSON y los recursos XML con un tipo MIME XML). - Inhabilita el espionaje con el encabezado
X-Content-Type-Options: nosniff
. Sin este encabezado, Chrome realiza un análisis de contenido rápido para intentar confirmar que el tipo es correcto, pero, como tiende a permitir respuestas para evitar bloquear elementos como archivos JavaScript, es mejor que lo hagas tú mismo.
Para obtener más información, consulta el artículo sobre CORB para desarrolladores web o nuestra explicación detallada de CORB.
¿Por qué debería importarte el aislamiento de sitios a los desarrolladores web?
En su mayor parte, el aislamiento de sitios es una función del navegador en segundo plano que no se expone directamente a los desarrolladores web. Por ejemplo, no hay una API nueva expuesta a la Web que debas aprender. En general, las páginas web no deberían poder distinguir la diferencia cuando se ejecutan con o sin aislamiento de sitios.
Sin embargo, hay algunas excepciones a esta regla. Habilitar el aislamiento de sitios conlleva algunos efectos secundarios sutiles que podrían afectar tu sitio web. Mantenemos una lista de problemas conocidos del aislamiento de sitios y, a continuación, explicamos los más importantes.
El diseño de página completa ya no es síncrono
Con el aislamiento de sitios, ya no se garantiza que el diseño de página completa sea síncrono, ya que los marcos de una página ahora pueden distribuirse en varios procesos. Esto podría afectar a las páginas si se supone que un cambio de diseño se propaga de inmediato a todos los marcos de la página.
A modo de ejemplo, consideremos un sitio web llamado fluffykittens.example
que se comunica con un widget social alojado en social-widget.example
:
<!-- https://fluffykittens.example/ -->
<iframe src="https://social-widget.example/" width="123"></iframe>
<script>
const iframe = document.querySelector('iframe');
iframe.width = 456;
iframe.contentWindow.postMessage(
// The message to send:
'Meow!',
// The target origin:
'https://social-widget.example'
);
</script>
Al principio, el ancho de <iframe>
del widget de redes sociales es de 123
píxeles. Sin embargo, la página FluffyKittens cambia el ancho a 456
píxeles (activa el diseño) y envía un mensaje al widget de redes sociales, que tiene el siguiente código:
<!-- https://social-widget.example/ -->
<script>
self.onmessage = () => {
console.log(document.documentElement.clientWidth);
};
</script>
Cada vez que el widget de redes sociales recibe un mensaje a través de la API de postMessage
, registra el ancho de su elemento <html>
raíz.
¿Qué valor de ancho se registra? Antes de que Chrome habilitara el aislamiento de sitios, la respuesta era 456
. El acceso a document.documentElement.clientWidth
fuerza el diseño, que solía ser síncrono antes de que Chrome habilitara el aislamiento de sitios. Sin embargo, con el aislamiento de sitios habilitado, el nuevo diseño del widget social de origen cruzado ahora se realiza de forma asíncrona en un proceso independiente. Por lo tanto, la respuesta ahora también puede ser 123
, es decir, el valor anterior de width
.
Si una página cambia el tamaño de un <iframe>
de origen cruzado y, luego, le envía un postMessage
, es posible que, con el aislamiento de sitios, la trama receptora aún no conozca su nuevo tamaño cuando reciba el mensaje. En términos más generales, esto podría dañar las páginas si se supone que un cambio de diseño se propaga de inmediato a todos los marcos de la página.
En este ejemplo en particular, una solución más sólida establecería el width
en el marco superior y detectaría ese cambio en el <iframe>
escuchando un evento resize
.
Es posible que los controladores de descarga se agoten con mayor frecuencia.
Cuando se navega o se cierra un marco, el documento anterior, así como los documentos de submarcos incorporados en él, ejecutan su controlador unload
. Si la navegación nueva se produce en el mismo proceso de renderización (p.ej., para una navegación del mismo origen), los controladores unload
del documento anterior y sus submarcos pueden ejecutarse durante un tiempo arbitrariamente largo antes de permitir que se confirme la navegación nueva.
addEventListener('unload', () => {
doSomethingThatMightTakeALongTime();
});
En esta situación, los controladores unload
en todos los fotogramas son muy confiables.
Sin embargo, incluso sin el aislamiento de sitios, algunas navegaciones de marcos principales son multiproceso, lo que afecta el comportamiento del controlador de descarga. Por ejemplo, si navegas de old.example
a new.example
escribiendo la URL en la barra de direcciones, la navegación de new.example
se realiza en un proceso nuevo. Los controladores de descarga para old.example
y sus submarcos se ejecutan en el proceso old.example
en segundo plano, después de que se muestra la página new.example
, y los controladores de descarga anteriores se cancelan si no terminan dentro de un tiempo de espera determinado. Debido a que es posible que los controladores de descarga no finalicen antes del tiempo de espera, el comportamiento de descarga es menos confiable.
Con el aislamiento de sitios, todas las navegaciones entre sitios se convierten en navegaciones entre procesos, de modo que los documentos de diferentes sitios no compartan un proceso entre sí. Como resultado, la situación anterior se aplica en más casos, y los controladores de descarga en <iframe>
suelen tener los comportamientos en segundo plano y de tiempo de espera descritos anteriormente.
Otra diferencia que resulta de Site Isolation es el nuevo ordenamiento en paralelo de los controladores de descarga: sin Site Isolation, los controladores de descarga se ejecutan en un orden estricto de arriba abajo en todos los fotogramas. Sin embargo, con el aislamiento de sitios, los controladores de descarga se ejecutan en paralelo en diferentes procesos.
Estas son consecuencias fundamentales de habilitar el aislamiento de sitios. El equipo de Chrome está trabajando para mejorar la confiabilidad de los controladores de descarga para casos de uso comunes, siempre que sea posible. También estamos al tanto de los errores en los que los controladores de descarga de submarcos aún no pueden usar ciertas funciones y estamos trabajando para resolverlos.
Un caso importante para los controladores de descarga es enviar pings de fin de sesión. Por lo general, se hace de la siguiente manera:
addEventListener('pagehide', () => {
const image = new Image();
img.src = '/end-of-session';
});
Un enfoque mejor y más sólido a la luz de este cambio es usar navigator.sendBeacon
en su lugar:
addEventListener('pagehide', () => {
navigator.sendBeacon('/end-of-session');
});
Si necesitas más control sobre la solicitud, puedes usar la opción keepalive
de la API de Fetch:
addEventListener('pagehide', () => {
fetch('/end-of-session', {keepalive: true});
});
Conclusión
El aislamiento de sitios dificulta que los sitios web no confiables accedan a información de tus cuentas en otros sitios web o la roben, ya que aísla cada sitio en su propio proceso. Como parte de esto, CORB intenta mantener los recursos de datos sensibles fuera del proceso del renderizador. Nuestras recomendaciones anteriores te garantizan que aproveches al máximo estas nuevas funciones de seguridad.
Gracias a Alex Moshchuk, Charlie Reis, Jason Miller, Nasko Oskov, Philip Walton, Shubhie Panicker y Thomas Steiner por leer una versión preliminar de este artículo y enviar sus comentarios.