Los atacantes cibernéticos están cultivando continuamente sus métodos para evadir la detección. ¿Sabías que pueden ocultar una página web aparentemente inocua con una capa invisible que contiene enlaces maliciosos?. Este método de ataque, conocido como Clickjacking, podría hacer que actives tu cámara web o transfieras dinero desde tu cuenta bancaria.
En esta publicación, describimos los diferentes tipos de ataques de Clickjacking cómo funciona con un ejemplo real. Por supuesto, también te enseñaremos cómo defenderte mejor contra esta amenaza a la seguridad de la aplicación.
Tabla de Contenido
Qué es Clickjacking
Clickjacking es un ataque que engaña a un usuario para que haga clic en un elemento de la página web que es invisible o está disfrazado de otro elemento (HTML). Esto puede hacer que los usuarios descarguen malware, visiten páginas web maliciosas, proporcionen credenciales o información confidencial, transfieran dinero o compren productos en línea sin darse cuenta.
Normalmente, el clickjacking se realiza mostrando una página invisible o un elemento HTML, dentro de un iframe, en la parte superior de la página que ve el usuario. El usuario cree que está haciendo clic en la página visible, pero de hecho está haciendo clic en un elemento invisible en la página adicional transpuesta encima.
La página invisible podría ser una página maliciosa o una página legítima que el usuario no tenía la intención de visitar, por ejemplo, una nueva ventana de publicidad habitualmente visto en páginas de descargas.
Variaciones del ataque de Clickjacking
Según la naturaleza de la operación específica, el ataque puede asumir diferentes nombres. Considera, por ejemplo, las siguientes variantes:
- Likejacking: este tipo de ataque tiene como objetivo captar los clics de los usuarios y redirigirlos a ” Me gusta” en una página de Facebook u otras redes sociales.
- Cookiejacking: en este caso, se lleva al usuario a interactuar con un elemento de la interfaz de usuario, por ejemplo, a través de arrastrar y soltar, y para proporcionar al atacante las cookies almacenadas en su navegador. De esta manera, el atacante podría realizar acciones en el sitio web objetivo en nombre del usuario.
- Filejacking: con este tipo de ataque, el usuario permite al atacante acceder a su sistema de archivos local y tomar archivos.
- Cursorjacking: esta técnica cambia la posición del cursor a un lugar diferente de donde el usuario lo percibe. De esta forma, el usuario cree que está realizando una acción mientras en realidad está realizando otra.
- Ataques al administrador de contraseñas: este tipo de ataque tiene como objetivo engañar a los administradores de contraseñas para que aprovechen su funcionalidad de autocompletar.
Esas son solo algunas de las muchas otras posibles variantes de clickjacking. Incluso si existen muchas variantes, ten en cuenta que el principio básico en el que se basan es el mismo: capturar la acción de un usuario a través de un truco de IU (Interfaz de Usuario).
Ejemplo de Ataque de Clickjacking
Para entender los detalles detrás de un ataque de clickjacking, echemos un vistazo a cómo puede ocurrir en la práctica. Esto te ayudará a conocer su comportamiento y a elaborar una estrategia para evitarlo.
Configuración de entorno
Empecemos por clonar la aplicación de ejemplo del repositorio de GitHub que acompaña a este artículo. Ejecuta el siguiente comando en tu máquina:
git clone https://github.com/auth0-blog/clickjacking-sample-app.git
Una vez completada la descarga, instala las dependencias del proyecto moviéndote en la carpeta del proyecto y ejecutando este comando:
cd clickjacking-sample-app/
npm install
Ahora puede lanzar el sitio web vulnerable del proyecto de muestra escribiendo lo siguiente:
npm start
Por último, abre tu navegador y navega hasta la dirección http://localhost:3000. Deberías ver la siguiente página:
El proyecto implementa una página de streaming de películas ficticio. Además de permitirte reproducir una película, también puedes comprar el DVD correspondiente. Sin embargo, necesitas una sesión autentificada para reproducir y comprar una película. Para simplificar las cosas, este proyecto no implementa un proceso de autenticación real. Puedes simular una sesión autentificada haciendo clic en el enlace de sesión válida (Valid session) dentro del mensaje que aparece en la parte inferior de la página. Después de obtener la sesión de usuario simulada, ese mensaje desaparece.
Lanzar el ataque de clickjacking
Una vez que el sitio web de la película está funcionando, vas a configurar el ataque de clickjacking a él. Ejecutarás otro sitio web, el sitio web del atacante, cuyo código tomará el clic y lo redirigirá al sitio web de la película sin que te des cuenta.
Así que, vamos a ejecutar el sitio web del atacante ejecutando el siguiente comando en una ventana de terminal:
node attacker-server.js
A continuación, abre una nueva pestaña o una nueva instancia de su navegador y navega hasta http://localhost:4000. Deberías ver la siguiente página:
Esta página te promete unas vacaciones increíbles con sólo hacer clic en el botón Accept the prize! (¡Aceptar el premio!) Esto parece no tener ninguna relación con el sitio web de la película. Sin embargo, si haces clic en el botón, en realidad estás comprando el DVD en el sitio web de la película. Puedes comprobarlo abriendo la herramienta de desarrollo de tu navegador y analizando el tráfico de Red mientras haces clic en el botón. Este es un ejemplo de este seguimiento en Firefox DevTools:
Puedes observar una solicitud HTTP POST al punto final http://localhost:3000/purchase del sitio web de la película.
¿Cuál es la relación entre este sitio web y el sitio web de la película? Lo descubrirás en un momento.
Anatomía del ataque
Para entender lo que ha sucedido, echemos un vistazo a la página del sitio web del atacante. Desplázate a la carpeta views
y abre la página index.ejs
. El cuerpo de la página tiene el siguiente aspecto:
<!-- views/index.ejs -->
<html lang=en>
<head>
<!-- ...omitido... -->
</head>
<body>
<div id="attacker_website">
<h1>You Are The Winner!!!</h1>
<h2>You won an awesome tropics holiday!</h2>
<img alt="Tropical Holiday" src="images/tropical-holiday.jpg">
<h2>Accept it by clicking the button below.</h2>
<button type="submit">Accept the prize!</button>
</div>
<iframe id="vulnerable_website" src="https://localhost:3000">
</iframe>
</body>
</html>
Su contenido es una plantilla EJS con dos elementos principales:
- La parte visible de la página está definida por el div con el id
attacker_website
. - El iframe con el id
vulnerable_website
apunta al sitio web de la película, pero en realidad, no se ve en la página del atacante.
El truco que conecta los dos sitios web lo realizan las reglas CSS que definen la posición y la visibilidad de esos elementos. Echemos un vistazo a ellas:
<!-- views/index.ejs -->
<html lang=en>
<head>
<!-- ... codigo existente... -->
<style>
#vulnerable_website {
position:relative;
opacity:0.0;
width:800px;
height:900px;
top:75px;
left: -95px;
z-index:2;
padding-left:80px;
}
#attacker_website {
position:absolute;
z-index:1;
}
#attacker_website button {
margin-left:100px;
}
</style>
</head>
<!-- ... codigo existente... -->
</html>
Como puedes ver, el iframe vulnerable_website
tiene asignado el valor 0.0
para su opacidad, lo que lo hace transparente. Además, está posicionado de forma que se superpone al div attacker_website
. Puedes ver cómo el iframe se superpone al div ajustando el valor de opacidad del iframe a 0.5
. Después de cambiar ese valor, reinicia el sitio web del atacante. Deberías ver la página del atacante como se muestra en la siguiente imagen:
Se ve que el botón Accept the prize! se superpone al botón Buy DVD del sitio web de la película.
La propiedad z-index
completa el trabajo: el iframe invisible está sobre el div del atacante. Así, los usuarios creen que están haciendo clic en el botón Accept the prize!, pero en realidad están pulsando el botón Buy DVD
Ahora que sabes cómo funciona un ataque de clickjacking, debería saber que esta técnica también se conoce como redireccionamiento de IU o UI redressing.
Mitigación del Clickjacking
Ahora sabes cómo funcionan los ataques de Clickjacking. Analicemos cómo puedes prevenirlos y hacer que tu sitio web sea más seguro. Hay dos formas generales de defenderse del Clickjacking:
- Métodos del lado del cliente: el más común se llama Frame Busting. Los métodos del lado del cliente pueden ser efectivos en algunos casos, pero se considera que no son las mejores prácticas, ya que pueden evitarse fácilmente.
- Métodos del lado del servidor: el más común es X-Frame-Options. Los expertos en seguridad recomiendan los métodos del lado del servidor como una forma eficaz de defenderse contra el Clickjacking/secuestro de clics.
Acerca de Frame Busting
Dado que los ataques de clickjacking aprovechan los iframes, puedes pensar que aplicar algún tipo de defensa del lado del cliente que impida que tu sitio web se cargue en iframes puede protegerlo. Esta técnica, conocida como frame-busting, puede implementarse con unas pocas líneas de JavaScript.
<script type="text/javascript">
if (top != window) {
top.location = window.location;
}
</script>
¿Seguridad a través de JavaScript? Si crees que esto suena como una mala idea, probablemente tengas razón. Por ejemplo, algunos navegadores o extensiones del navegador pueden bloquear la recarga automática. Además, el atacante puede construir su página de manera que neutralice esa defensa. Por ejemplo, el atacante puede simplemente añadir el siguiente script a su página:
<script type="text/javascript">
window.onbeforeunload = function() {
return false;
};
</script>
Manejando el evento onbeforeunload
, el atacante intenta deshabilitar la salida de la página actual. Este enfoque podría no funcionar en algunos navegadores ya que podría requerir la confirmación del usuario. Pero el atacante tiene otras opciones. Por ejemplo, puede utilizar el atributo sandbox
del iframe, como se muestra a continuación:
<iframe id="vulnerable_website"
src="https://localhost:3000"
sandbox="allow-scripts allow-forms allow-same-origin">
</iframe>
En este caso, el atacante especifica que el contenido del iframe tiene permiso para ejecutar scripts (allow-scripts
), para enviar formularios (allow-forms
), y para ser tratado como si fuera del mismo origen (allow-same-origin
). No se especifica ningún otro permiso, por lo que el contenido del iframe no puede reemplazar el contenido de nivel superior, como habría permitido el valor allow-top-navigation
.
En otras palabras, las defensas del lado del cliente contra los ataques de clickjacking son fáciles de sortear y no se recomiendan excepto para mitigar el problema en los navegadores heredados.
Si quieres probar esta defensa del lado del cliente y la neutralización relacionada con el atacante, puedes descargar el mismo proyecto adaptado con el siguiente comando:
git clone -b client-side-defenses https://github.com/auth0-blog/clickjacking-sample-app.git
Acerca de X-Frame-Options
Un mejor enfoque para prevenir los ataques de clickjacking es pedir al navegador que bloquee cualquier intento de cargar tu sitio web dentro de un iframe. Puedes hacerlo enviando la cabecera HTTP X-Frame-Options
.
X-Frame-Options se introdujo originalmente como un encabezado de respuesta no oficial en Internet Explorer 8 y se adoptó rápidamente en otros navegadores. El encabezado proporciona al propietario del sitio web control sobre el uso de iframes u objetos, de modo que la inclusión de una página web dentro de un marco/frame puede prohibirse con la directiva deny
:
X-Frame-Options: deny
Alternativamente, el framing puede restringirse al mismo origen que el sitio web utilizando la directiva sameorigin
:
X-Frame-Options: sameorigin
o nombrando a un sitio web utilizando la directiva allow-from
:
X-Frame-Options: allow-from https://sitio-web-normal.com
Continuando con el ejemplo original, edita el archivo server.js
como se muestra a continuación:
// server.js
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const port = 3000;
const app = express();
app.set('views', './templates');
app.set('view engine', 'ejs');
//👇 nuevo código
app.use(function(req, res, next) {
res.setHeader('X-Frame-Options', 'sameorigin');
next();
});
// ...código existente...
Has configurado un middleware Express que añade la cabecera HTTP X-Frame-Options
a cada respuesta para el navegador. El valor asociado a esta cabecera de respuesta es sameorigin
, que indica al navegador que sólo las páginas del mismo sitio web pueden incluir esa página dentro de un iframe.
Con esta restricción, un atacante no podrá utilizar la técnica mostrada anteriormente para capturar los clics de los usuarios. Puedes comprobar que esta defensa funciona cambiando la opacidad del iframe en la página del atacante:
<!-- views/index.ejs -->
<html lang=en>
<head>
<!-- ...existing markup... -->
<style>
#vulnerable_website {
position:relative;
opacity:0.5; //👈
...
Una vez que apliques este cambio, reinicia el sitio web del atacante. Deberías ver algo similar a la siguiente imagen:
Esta vez el contenido del iframe está bloqueado.
Para probar este enfoque, puedes descargar la variación del proyecto de aplicación de ejemplo con el siguiente comando:
git clone -b x-frame-options https://github.com/auth0-blog/clickjacking-sample-app.git
Políticas de Seguridad de Contenido (CSP)
Los principales navegadores soportan la cabecera X-Frame-Options
. Sin embargo, nunca se ha estandarizado, por lo que puede haber navegadores que no lo soporten. Un enfoque estándar alternativo para evitar los ataques de clickjacking es el uso de directivas específicas de la Content Security Policy (CSP).
Por ejemplo, después de restaurar el proyecto de la aplicación de ejemplo a su estado original, cambia el contenido del archivo server.js
como se muestra a continuación:
// server.js
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const port = 3000;
const app = express();
app.set('views', './templates');
app.set('view engine', 'ejs');
//👇 nuevo código
app.use(function(req, res, next) {
res.setHeader("Content-Security-Policy", "frame-ancestors 'self';");
next();
});
// ...código existente...
CSP generalmente se implementa en el servidor web como un encabezado de retorno:
Content-Security-Policy: policy
La protección recomendada contra el clickjacking es incorporar la directiva frame-ancestors
. La directiva frame-ancestors 'none'
es similar en comportamiento a la directiva deny
de X-Frame-Options . La directiva frame-ancestors 'self'
es ampliamente equivalente a la directiva sameorigin
de X-Frame-Options.
Para probar el enfoque CSP para defender la aplicación de ejemplo del clickjacking, descarga el proyecto ejecutando este comando:
git clone -b content-security-policy https://github.com/auth0-blog/clickjacking-sample-app.git
Comprobador de Ataques Clickjacking
Finalmente, una herramienta para comprobar sitios web vulnerables a ataques de Clickjacking.
El siguiente script de Python está diseñado para verificar si un sitio web es vulnerable al ataque de Clickjacking y guarda el resultado en un archivo Vulnerable.txt.
Funciona de la siguiente manera:
git clone https://github.com/saleem8054/clickjack.git
cd clickjack
python3 clickjack.py archivo_websites.txt
¿Te gustaría otra explicación de otro tipo de ataque? Déjanos saber a través de los comentarios…