Nota: en algún momento posterior a la publicación de este artículo (no hay causa-efecto 😉) Facebook añadió el atributo que menciono en el contenido y el ejemlo que relato en vídeo no funciona al compartirlo allí. No obstante si pruebas a compartir un enlace en cualquier otro sitio que no le añada el atributo mencionado, funcionará igualmente la vulnerabilidad. Sustituye Facebook por otra cosa. En el ejemplo descargable puedes abrir la prueba de concepto desde la raíz (index.html
) y en la página original verás una página de login de Facebook "de pega"). Lo importante es conocer el problema y que no seamos una de las páginas que lo sufre. Sigue leyendo...
Te reto a que hagas una prueba sencilla...
Descarga este archivo, descomprímelo en una carpeta (está creado usando 7-Zipel mejor compresor en mi opinión), y colócalo en un dominio cualquiera al que tengas acceso (en tu blog, sitio web, etc...).
Cambia la dirección que aparece en el código JavaScript de la página "testOpener.html" para que apunte al dominio en el que lo has colocado.
Ahora abre tu cuenta de Facebook y comparte la dirección a la página llamada testOpenener.html.
Una vez compartido, pulsa sobre el enlace que genera Facebook.
Para mostrarte cómo va, aunque no lo cuelgues en ningún lado, he grabado un pequeño vídeo colgándolo en mi dominio y mostrando lo que ocurre:
Lo que está pasando es que Facebook, al igual que otras muchas aplicaciones, sufre una vulnerabilidad llamada "tabnabbing".
En este caso la estamos aprovechando para que cuando alguien llegue a nuestra página maliciosa desde Facebook, sustituimos la página original en la pestaña desde la que viene el usuario, y le mostramos una página idéntica al login de Facebook.
Si el usuario no presta mucha atención (que es lo lo habitual), no se dará cuenta de que está en otro dominio (especialmente si compramos uno con un nombre parecido), y simplemente pensará que se le ha caducado la sesión y que tiene que volver a entrar.
Al introducir sus credenciales en la página de login maliciosa, el atacante tendrá acceso a su cuenta y podrá hacer de todo con ella.
¿Por qué se produce esto?
El problema viene de la manera en la que funcionan los navegadores respecto a los enlaces.
Por un lado, como todo desarrollador web sabe (o debería saber), por seguridad y privacidad no se permite acceder desde el script de una página que está en un dominio a nada que se encuentre en otro dominio. Es lo que se llama Cross-Origin Security, o seguridad entre dominios. Es decir, los dominios están aislados unos de otros.
Además, si en un enlace HTML establecemos el atributo target con el valor "_blank" conseguiremos que el enlace se abra en una ventana/pestaña aparte.
La vulnerabilidad se sustenta en dos particularidades de estos dos hechos:
- La propiedad location del objeto window no está sujeta a la limitación de seguridad entre dominios.
- Cuando un enlace se abre con target=_blank se establece automáticamente la propiedad opener en la nueva ventana, que da acceso a la ventana original. Esto además ocurre también cuando abrimos el enlace usando el método window.open con JavaScript.
Esta particularidad lo que nos permite es montar fácilmente un ataque como el anterior, pues basta con meter un código como este en la página de destino:
<script>
var op = window.opener;
console.log(op);
if (op) {
op.location = 'http://www.jasoft.org/otros/EjemploPhishing/GMail.html';
}
</script>
para poder redirigir la página en la que estaba originalmente el enlace a la dirección que nosotros queramos.
Es bien fácil ver cómo esto se puede usar esta técnica para determinar de manera sencilla desde dónde viene un usuario a nuestro enlace malicioso, y enviarlo a la página de login falsa apropiada según el servicio, recolectando claves de cantidad de servicios diferentes. Por suerte casi todos los servicios serios (GMail, Outlook, Dropbox, OneDrive... menos Facebook) tienen esto en cuenta y lo evitan de la manera que vamos a ver a continuación.
¿Cómo lo evitamos en nuestras aplicaciones?
Por suerte este tipo de vulnerabilidad tiene fácil solución. El caso es conocerla y ser consciente de ella, algo que ya sabes tras haber leído este artículo ;-)
Lo único que tenemos que hacer es añadir el siguiente atributo a nuestros enlaces que tengan algún valor asignado para target:
rel="noopener"
De este modo el navegador no asignará la propiedad opener de la nueva ventana y el atacante no podrá sacar partido a la vulnerabilidad.
En navegadores antiguos este atributo no funciona, pero la solución es emplear un valor mucho más antiguo y también efectivo:
rel="noreferrer"
(¡fíjate que lleva tres "erres" en total!)
Este atributo lo que hace es que, además de no establecerse la propiedad opener tampoco envía la cabecera REFERER que le indica al servidor desde dónde viene la petición.
Por mayor seguridad, lo mejor es poner ambos valores, así:
rel="noopener noreferrer"
Con esto evitamos la vulnerabilidad generada por los enlaces en ventana aparte.
Si nuestra aplicación hace uso de window.open para abrir los enlaces, en este caso la vulnerabilidad se soluciona con un código similar a este:
var nuevaVentana = window.open('http://www.loquesea.com/');
nuevaVentana.opener = null;
Es decir, una vez abierta la ventana y guardada su referencia en una variable, establecemos manualmente el valor de opener a nulo, evitando que se pueda utilizar desde la página que se está cargando.
En resumen
Esta vulnerabilidad es muy sencilla de explotar y los navegadores no pueden hacer nada para evitarla salvo que cambiaran por completo el comportamiento por defecto de los enlaces y ventanas abiertas desde JavaScript. Aunque lo hiciesen en el futuro, todos los navegadores actuales y pasados están afectados.
Por ello, está únicamente en nuestra mano tenerla en cuenta en las aplicaciones y evitarla para mayor seguridad de nuestros usuarios.
Por suerte es extremadamente sencilla de solucionar, así que no tienes disculpa para no hacerlo :-)
* Al principio escribí el post albergando la página maliciosa en mi blog para facilitar que hicieses pruebas. A los pocos minutos me llegó este mensaje de email de Google avisándome a través de las Webmaster Tools que tenía contenido sospechoso de "ingeniería social" en mi sitio. Alucinante la eficiencia de Google para estas cosas y otro motivo más para darse de alta en esta herramienta. Por eso lo he cambiado para que apunte al 7-Zip y te lo puedas descargar.
¡Espero haberte ayudado!