JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

Qué es la vulnerabilidad 'tabnabbing' y cómo evitarla en tus aplicaciones web

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:

Agujeros-Seguridad-Navegadores-JASoft-pLo 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:

  1. La propiedad location del objeto window no está sujeta a la limitación de seguridad entre dominios.
  2. 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!

José Manuel Alarcón José Manuel Alarcón
Fundador de campusMVP.es, el proyecto de referencia en formación on-line para programadores en lengua española. Autor de varios libros y cientos de artículos. Galardonado como MVP de Microsoft desde 2004. Gallego de Vigo, amante de la ciencia y la tecnología, la música y la lectura. Ayudando a la gente en Internet desde 1996.
Descarga GRATIS mi último libro (no técnico): "Tres Monos, Diez Minutos".
Banner

Comentarios (7) -

unamgiuete

"fíjate que lleva tres "erres" en total" Entiendo que lo tuyo es la programación no contar , porque Referrer lleva cuatro erres

Responder

by Jose M. Alarcon

Entiendo que lo tuyo no es leer con detenimiento (ni puntuar, porque te falta una coma), ya que le he puesto las 4 "erres" donde había que ponerlas, y en donde pone solo 3 ("la cabecera REFERER") es correcto porque se llama así aunque la palabra original no se escriba así. Si sigues el enlace y lees el artículo de la Wikipedia, lo primero que pone es precisamente que eso:

   [i]The HTTP referer (originally a misspelling of referrer)...[/]

De nada.

Responder

Miguel Angel

Muchas gracias por compartir tus conocimientos con nosotros!!!

Responder

Me ha encantado tu artículo. Pero te escribo para comunicar que el archivo 7Z no se puede descargar. A pesar de esto, sigue así, tu web es genial, llevo horas leyendo artículos tuyos, el que más me ha gustado es el de poder hacer hablar al navegador, eres un genio!

Responder

by Jose M. Alarcon

Hola Dani:

De genio nada:sólo trabajador, y que me gusta divulgar. Los genios son los que hacen que eso pueda funcionar en un navegador 😊

Dado que has dejado un correo falso, dudo que te llegue esto, pero bueno (qué cruz: ¿qué pensáis, que me voy a dedicar enviaros spam a los que leéis el blog? 🤦‍♂️ En fin...).

El 7z no descargaba porque no tenía el tipo MIME adecuado en el servidor. Cuando lo migré a Azure me olvidé de meterlo. ya está. Ahora desca sin problemas. No lo dejo en un ZIP porque sino Chrome seguramente diría también que es un archivo peligroso.

Saludos.

Responder

Hola

Despues de hacer varias pruebas con distintos navegadores, en el único que sigue funcionando esta vulnerabilidad eran en Microsoft Edge.

Saludos

Responder

by Jose M. Alarcon

Hola:

Es que el artículo tiene más de 3 años y Facebook, aunque tardaron, ahora ya le meten a todos los enlaces el rel="noopener noreferrer".

Pero la vulnerabilidad sigue existiendo y por eso conviene ponerle ese atributo a todos los enlaces. De hecho si modificas ligeramente el ejemplo metiendo una página más para abrir el enlace y que haya un referrer verás que te muestra la página simulada de Facebook sin ningún problema.

Es decir, no funciona en Facebook ya porque tienen el atributo, pero en cualquier página que permita compartir enlaces arbitrarios y que no le metan ese atributo, sí funciona este tipo de ataque.

En Edge (supongo que te refieres al que viene nativo con Windows, no al nuevo Edge, que pronto será el nativo y ahora te instalas por separado), porque el nuevo Edge usa Chromium por debajo y le hará caso a rel="noopener noreferrer" como es debido.

En definitiva: la vulnerabilidad sigue existiendo y el artículo sigue siendo válido aunque ya no en Facebook. Meteré un comentario, gracias.

Saludos.

Responder

Agregar comentario