Introducción
Los atacantes suelen explotar marcas confiables en sus señuelos de acceso inicial, ya sea falsificando sus logotipos o abusando de funciones legítimas. En los últimos meses, Huntress investigó incidentes que comenzaron con señuelos ClickFix que usaban ChatGPT, Google Docs y muchas otras herramientas confiables. En un método de ataque que ya afectó al menos a tres clientes de Huntress, un actor de amenazas que usaba resultados de búsqueda pagados llevó a las víctimas a una ingeniería social estilo ClickFix que, como suele suceder, les pide ejecutar un comando en su terminal.
Pero el comando usado en este señuelo aprovecha, de forma inusual, una utilidad de red de décadas de antigüedad (y poco usada), finger, para iniciar una secuencia de scripts de ataque enrevesada y muy ofuscada que, finalmente, llevó a infectar la computadora de la víctima con al menos tres formas completamente distintas de infostealer y malware de acceso remoto. Los actores de amenazas han estado abusando de la utilidad finger, que (aunque está presente en la mayoría de las computadoras modernas) no es bien comprendida por la mayoría de los usuarios, en ataques ClickFix desde hace al menos un año.
En el curso de la investigación, el equipo de Adversary Tactics de Huntress Labs observó una cadena de infección completa, capturó y realizó ingeniería inversa de los componentes, y analizó el tráfico de red enviado y recibido por las distintas cargas útiles, con el fin de construir un panorama completo del método de ataque.
Una búsqueda en Google, un inicio de sesión falso de Amazon y una prueba CAPTCHA falsa
Figura 1: El resultado patrocinado de Google que llevaba a una página falsa de inicio de sesión de Amazon
El ataque comenzó con una búsqueda simple. El primer resultado patrocinado en el momento de los ataques para la palabra clave "amazon business" (que se muestra arriba) estaba alojado en un subdominio con apariencia engañosa de un dominio controlado por el atacante: orders-amazon[.]com[.]advancedfences[.]com.
El enlace malicioso redirigía a una página falsa de inicio de sesión de Amazon, alojada en un espacio de almacenamiento privado en la cloud de Google Sites, sites.google[.]com/view/ch-pc/sign-in. La página le pedía al usuario ingresar su correo electrónico o número de teléfono.
Figura 2: Página falsa de inicio de sesión de Amazon
Después de que el usuario presiona "enviar", la página muestra un diálogo falso de prueba CAPTCHA. Al hacer clic en un botón con la etiqueta "No soy un robot", se guarda un comando pastejacked en el portapapeles del usuario, y una ventana emergente le indica que ejecute el comando en el cuadro Ejecutar de Windows.
Figura 3: El ataque ClickFix le pide al usuario pegar un comando en su cuadro de diálogo Ejecutar en computadoras con Windows
Aunque el siguiente análisis cubre cargas útiles específicas de Windows, el ataque era multiplataforma: los usuarios que visitaron la página con un User-Agent de navegador que hace referencia a macOS recibieron instrucciones alternativas para ejecutar un script en la aplicación Terminal de Mac, pero la URL de destino en ese caso—hxxp[://]ashevilleroofingcontractor[.]com/curl/bc9e2dac08fb4f83dddb44f89bf7082bb4134697fbf6a99ad8ce30c634e9fe8a—estaba fuera de línea en el momento en que Huntress realizó esta investigación.
Etapa 1: Darles literalmente el dato a los usuarios
Los comandos ingresados lanzan la utilidad integrada finger.exe para comunicarse con una cuenta de usuario específica en el dominio controlado por el atacante grillrecipespro[.]com.
El comando finger es antiguo, según los estándares de internet, y precede a la existencia de la web misma por casi dos décadas, según Wikipedia. En su época dorada, las personas que usaban internet interactuaban directamente con cuentas shell de Unix en servidores remotos; finger ofrecía una forma para que el dueño de una cuenta publicara su información de contacto, alguna cita ingeniosa, incluso arte ASCII, en lo que era esencialmente una cartelera personal colocada en la puerta de su oficina virtual, dentro de un archivo llamado .plan, almacenado en la raíz del directorio de la cuenta shell del usuario. Pero durante la mayor parte del último año, finger ha desarrollado una nueva vida como LOLbin del que se abusa en ataques ClickFix.
En este ataque, el actor de amenazas colocó un script de Windows en un archivo .plan vinculado a una cuenta de usuario. El comando ClickFix que invoca finger está, en sí mismo, ofuscado (de forma rudimentaria) al separar los caracteres que componen el comando con una coma, un acento circunflejo (^), un guion y guiones bajos, que la interfaz de comandos de Windows ignora convenientemente. El comando, pegado en un editor de texto, se ve así:
Figura 4: El texto del comando ClickFix
El comando en sí no es fácilmente visible en el cuadro de diálogo Ejecutar porque los actores de amenazas construyeron la línea de comando con un sufijo que usa espacios adicionales y caracteres de guion para seguir al comando real. Para un usuario final, el efecto es que el contenido del cuadro Ejecutar parece decir, simplemente, "Presiona la tecla Enter".
Figura 5: El cuadro de diálogo Ejecutar oculta el comando
El efecto de la línea de comando, sin embargo, está lejos de ser inofensivo. Le indica a la interfaz de comandos de Windows que ejecute el contenido del archivo .plan en el otro extremo del comando finger DLVBUCeFfF@grillrecipespro[.]com.
Figura 6: La parte superior del archivo .plan de la cuenta de usuario controlada por el adversario
El contenido del script dentro del archivo remoto .plan está "oculto" mediante el uso de 68 retornos de carro adicionales que llevan el contenido weaponizado más allá de la altura de pantalla de una consola de terminal típica. (Los comandos Finger transmiten texto plano por el puerto 79/tcp de forma predeterminada, lo que debería facilitar su detección o bloqueo, pero como ya nadie usa finger, la mayoría de las redes no bloquean este contenido.)
Bastante por debajo de la parte superior de la pantalla, el archivo .plan contiene un script con instrucciones para activar la primera etapa del ataque, que requiere un intérprete de Python ejecutable llamado ipyw32.exe incluido en una distribución de Python llamada IronPython. Entonces el script genera curl para descargar y descomprimir IronPython.3.4.2.zip desde la ubicación de su repositorio, github[.]com/IronLanguages/ironpython3/releases/download/v3.4.2/IronPython.3.4.2.zip.
Figura 7: ¿No te encanta cuando un .plan se arma solito?
"El script coloca el archivo ZIP de IronPython en el directorio Temp del usuario, como un archivo con extensión .pdf." Luego usa el comando tar (que ahora forma parte de las instalaciones modernas de Windows) para descomprimir el .zip; el script luego navega a la carpeta \net462 dentro de la estructura anidada del archivo descomprimido, y pasa un blob de datos de script de Python codificado en Base64 y comprimido con zlib directamente al programa ipyw32.exe como un indicador de comando.
El resultado final de este proceso obtiene y ejecuta el contenido de hxxp://grillmasterchef[.]com/90e4a147-1234-505c-a024-062e543b5df8/timer6, y aquí es donde se pone interesante.
Etapa 2: Enciende la parrilla
El archivo timer6 es un script de Python codificado en Base64, al que luego se le sustituyeron algunos caracteres del alfabeto latino por letras cirílicas. Como el esquema de codificación Base64 no interpreta caracteres cirílicos, una decodificación directa no funciona. El script revierte la sustitución de estas letras alternas de vuelta a caracteres ASCII, y luego decodifica el blob Base64.
Figura 8: La parte superior del Base64 de timer6 aún codificado (con la letra cirílica minúscula "Yo" resaltada), con las reglas de sustitución de caracteres cirílicos/latinos del script (recuadro)
Varios proveedores de ciberseguridad parecen creer que timer6 aprovecha un framework de simulación de adversarios ahora obsoleto llamado Veil, diseñado para ofuscar scripts de Python de Metasploit Meterpreter y hacerlos menos detectables durante pruebas de penetración. Eso es posiblemente acertado, pero no del todo correcto: al revisar el script timer6, parece aprovechar algunos aspectos del shellcode_inject/flat.py de Python de Veil—en particular, contiene el mismo indicador HeapCreate, el indicador HeapAlloc, el mismo patrón de copia de búfer y la misma secuencia de API nativa. Veil describe explícitamente este módulo como diseñado para la inyección de shellcode en línea, que es una de las cosas que hace timer6. Pero hay otros aspectos del comportamiento de timer6 que se apartan de lo que hace el paquete completo de Veil por defecto.
El contenido de timer6, una vez decodificado, es otro script de Python.
Figura 9: La segunda capa de timer6, un script de Python decodificado desde Base64, que contiene otra capa de decodificación para datos con XOR que se codificaron en Base64
Esta capa de shellcode está protegida con una clave XOR de 19 bytes (Hex: 84 0d ff da 80 29 b6 1b 52 9b 42 40 5d 55 aa 80 a5 7e 7c) que está incrustada dentro del script como un blob de Base64 separado.
Figura 10: La clave XOR está en la casa contigo en este momento
Una vez descomprimido y decodificado, el resultado de este script es un cargador de malware de tipo PE de Windows, que se ejecuta en cuanto el script lo decodifica. Este cargador de malware busca en el disco un archivo .ini específico que contiene una URL. Si encuentra la URL en el archivo .ini, descarga lo que haya al otro extremo (usando la cadena User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36), y luego realiza el descifrado RC4 del archivo descargado.
En este caso, el cargador se conectó a otra URL con temática de barbacoa, hxxps://grillmasterchef[.]com/90e4a147-1234-505c-a024-062e543b5df8/v6, y descifró el contenido, que era otro ejecutable de malware. La clave de descifrado RC4 se antepone como los primeros 64 bytes de este archivo v6.
El malware v6, una vez descifrado, el script lo inyecta automáticamente en la memoria. El consenso de los proveedores de seguridad es que se trata de un malware llamado Doina, que puede servir como mecanismo de entrega para otro malware. En 2024, el proveedor de seguridad Halcyon informó que Doina estuvo implicado como paso previo a ataques de ransomware, pero Doina tiene múltiples funciones y una arquitectura modular que lo hacen útil como RAT de propósito general, infostealer y herramienta de perfilado.
Inmediatamente después de que Doina empezó a ejecutarse, comenzó a comunicarse con el mismo servidor grillmasterchef del que se originó, enviando una serie de comunicaciones HTTPS POST, y luego obteniendo un archivo ZIP desde la URL hxxps://kiriosyka[.]com/KsxmmKiN5N0j/sqr-viewertr6: un archivo comprimido de 52 MB que contiene una instancia completa y portátil del intérprete de código Node.js, y un script index.js malicioso y muy ofuscado. El malware lo descomprime en la ubicación C:\ProgramData\NodeView, y luego ejecuta el intérprete (no malicioso) node.exe, pasándole el archivo index.js como argumento.
Figura 11: Contenido descomprimido del archivo sqr-viewertr6 file
También es notable que otros elementos de este ataque despliegan sus diversas cargas útiles, registros y archivos relacionados tanto en la raíz de la ruta C:\ProgramData\, como en carpetas debajo de ese directorio.
Etapa 3: subiendo la temperatura con más malware
Si bien index.js es en sí mismo una forma de malware, también está diseñado con una arquitectura modular capaz de descargar, descifrar e inyectar en memoria varios tipos de payloads maliciosos cifrados como malware sin archivos.
En esta investigación, el componente de Node descargó dos archivos adicionales, que luego comenzaron a enviar señales y a realizar actividades propias de malware. Los dos archivos recibieron nombres aleatorios que parecen GUID; uno tiene un tamaño de apenas 17 KB, y el otro supera los 19 MB. Ninguno tiene un encabezado PE identificable, y ambos presentan una entropía alta. Entonces, ¿qué está pasando aquí?
Los tres archivos forman parte de un mismo paquete. El componente index.js descifra ambos archivos usando AES-256-GCM, en el que los primeros 12 bytes de cada archivo son el valor nonce, y los siguientes 16 bytes son la clave. Luego ejecuta el archivo más pequeño.
Resulta que el más pequeño de los dos archivos es un inyector de DLL reflexivo basado en shellcode (o sRDI), que básicamente funciona como cargador del archivo más grande. El archivo más grande es un malware de robo de información, presuntamente Lumma Stealer. El componente sRDI inyecta el stealer en memoria mediante process hollowing, y el malware comienza a enviar señales de inmediato.
Como parte de su registro inicial con su C2, el malware stealer transmite el nombre del sistema, el nombre de usuario y otra información de perfil como parte de una conexión HTTPS POST inicial. Luego cambia de modo y se comunica mediante el protocolo websocket para el monitoreo continuo.
Figura 12: Captura de paquetes del tráfico de la sesión websocket generado por el malware, que recibe convenciones de nombres de archivo para buscar desde el servidor C2 (en rojo) y envía un identificador único y un "heartbeat" durante los periodos de inactividad (en azul).
La conexión websocket incluía la URL que apuntaba al paquete de descarga sospechoso de Lumma Stealer, además de nombres de archivo y otras cadenas que indican los programas de interés para el stealer:
Navegadores (Chrome, Edge, Firefox, Opera)
Aplicaciones de billeteras de criptomoneda (Ledger, Electrum, Atomic Wallet)
Administradores de contraseñas (LastPass, Dashlane, 1Password, NordPass, RoboForm)
Clientes de correo electrónico
Procesadores de comandos como PowerShell
Al igual que con muchos otros elementos de esta infraestructura del atacante, las direcciones C2 con las que se comunica el malware siguen una temática de parrillada: thegrilljournal[.]com y homelygrill[.]com se usan para la exfiltración tras un registro inicial en perfectgrillrecipes[.]com. El malware se origina en el dominio liokida[.]com (que, hasta donde podemos determinar, no es un término relacionado con parrilladas), y el stealer contiene este dominio incrustado dentro de sí mismo como una cadena. Una versión anterior del ataque también enlazaba al payload del stealer desde kiriosyka[.]com.
Curiosamente, el malware de Node, index.js, realiza dos tipos de actualizaciones periódicas: puede solicitar un archivo de actualización que contiene tanto los payloads ejecutables del stealer como del cargador reflexivo, junto con los archivos del intérprete de Node.js (que en total pesan alrededor de 58 MB), o puede obtener solo los archivos del payload (index.js y los dos archivos .tmp, con un peso de poco menos de 20 MB). Para obtener la actualización de menor tamaño, el malware llama a la misma URL agregando al final la cadena de consulta ?exclude_bins=true.
Cada solicitud de recuperación de archivo devuelve un archivo comprimido con un hash único, porque el servidor que aloja estos payloads agrega una cantidad aleatoria de bytes nulos al archivo en el momento de la solicitud. El payload dentro de los archivos comprimidos cambiaba una o dos veces por día.
Figura 13: Contenido descomprimido del archivo sqr-viewertr6 descargado con la cadena de consulta exclude_bins=true, que no incluye el ejecutable de Node
Finalmente, observamos otro componente malicioso más instalado como parte de la entrega de este paquete de malware: también se desplegó una copia pirateada de un RMM llamado NetSupport dentro del directorio C:\ProgramData bajo la carpeta no estándar Prodclear. La clave de licencia y la información de derechos de autor de este RMM indican que el RMM tiene al menos ocho años de antigüedad. El RMM mantiene extensos archivos de registro de su actividad dentro de un subdirectorio.
La comunicación de NetSupport ocurre mediante una conexión HTTPS que usa el puerto no estándar 725/tcp, y esta instalación en particular se comunica con la dirección IP 167.148.201[.]106. El tráfico C2 generado por el software NetSupport Client se conecta al archivo HTML fakeurl.htm en la misma dirección IP.
Figura 14: El ejecutable del software NetSupport Client fue firmado criptográficamente hace ocho años.
Etapa 4: Chef Boyardon't y la Gastro Infra
Como se mencionó anteriormente, los dominios .com de C2 y de entrega de payloads usados por el malware en su mayoría suenan como títulos de una revista de alta gama sobre cocina con carbón: GrillRecipesPro, TheGrillJournal, EmbersAndBites, GrillMasterChef, y HomelyGrill funcionan como dominios tanto de C2 como de entrega de payloads. Encontramos varias relaciones entre los dominios, desde servidores de alojamiento y DNS comunes hasta múltiples payloads que se comunican con los dominios o que se entregan desde ellos.
Figura 15: Mapa de relación que vincula los dominios C2 y el dominio de entrega de payloads Liokida con múltiples ejecutables de Lumma Stealer
Figura 16: Relaciones de URL, dominio y archivo entre los dominios C2 de Doina y el dominio de entrega de payloads Kiriosyka
Los dominios decididamente ajenos a la comida Liokida y Kiriosyka alojan los paquetes de payloads de Lumma Stealer/Node.js, así como varios otros payloads maliciosos que no se invocaron durante este ataque.
Figura 17: Patrones de URL comunes usados para entregar payloads desde los dominios Kiriosyka y Liokida
También observamos una dirección IP (167.148.201.106) usada como C2 para el payload de NetConnect Client RMM. La dirección IP se usa únicamente para alojar el sitio web legítimo de un restaurante ubicado en Detroit, pero no se ha observado que ese dominio sea abusado. El tráfico de C2 se conectó directamente a la dirección IP.
Figura 18: Dirección IP vinculada al dominio de un restaurante usada para comunicaciones de C2
Figura 19: El código desofuscado de Doina llama a la descarga de Lumma Stealer y la ejecuta
Mitigación
La mejor defensa contra ClickFix es que los usuarios sepan qué es y cómo funciona. Los ataques tienen éxito porque una gran proporción de usuarios simplemente no reconoce el riesgo de seguir una instrucción en pantalla. Si llegaste hasta aquí, cuéntales a tus colegas, familiares y amigos qué deben vigilar. Ninguna prueba CAPTCHA legítima pedirá jamás pegar una línea de texto arbitraria en una ventana de comandos del sistema operativo. Así no funcionan las pruebas CAPTCHA.
La función de anuncios pagados de Google puede alojar sin querer enlaces maliciosos, en una técnica conocida comúnmente como malvertising. En agosto, los analistas de Huntress hicieron ingeniería inversa de una muestra de MacSync Stealer recolectada de un incidente que comenzó cuando el usuario hizo clic en un resultado patrocinado de Google tras buscar cómo instalar Claude en una Mac.
Por suerte para los defensores, la forma en que se redirigen los clics de anuncios de Google para facturar al anunciante deja algunos indicadores clave para la detección: aclk en la ruta de la URL y gclid en las cadenas de consulta resultantes.
Figura 20: Los identificadores que usa Google para facturar a los anunciantes cuando los usuarios hacen clic en un resultado patrocinado
Estos parámetros indican que un usuario llegó a un sitio a través de un anuncio patrocinado por Google, incluso si redirecciones posteriores ocultan el origen original. Los investigadores pueden usar estos marcadores en el historial del navegador, los registros del proxy o la telemetría de URL para reconstruir la cadena desde el anuncio hasta el sitio malicioso y conectar campañas o dominios relacionados. Reportar estos identificadores a Google puede debilitar a los atacantes al cortarles el acceso al ecosistema de anuncios (al menos, hasta que creen una cuenta nueva y vuelvan a empezar).
Los clientes y partners de Huntress cuentan con una herramienta adicional en su arsenal: una nueva función llamada Attack Reduction ya está disponible como parte de Huntress Managed ESPM Early Access. Los ataques ClickFix suelen pedirles a los usuarios de Windows que abran el cuadro de diálogo Ejecutar de Windows para ingresar un comando; esta función permite a los administradores activar o desactivar el acceso al cuadro Ejecutar para la mayoría de los usuarios que nunca lo necesitan. (Mira cómo funciona y qué bloquea.)
Figura 21: Vista de cerca de la función Attack Reduction que impide que los usuarios abran el cuadro Ejecutar en ESPM Early Access
No detiene todas las formas de ClickFix; de hecho, a veces los atacantes piden a los usuarios que abran PowerShell, la ventana de comandos, o incluso que ingresen comandos en la barra de direcciones de Windows Explorer, pero es un método muy comúnmente abusado que la mayoría de las personas con endpoints administrados no extrañará.
Como se informó en nuestro recién publicado Tragic Quadrant, ClickFix representó alrededor del 2,2% de las señales de detección de Detección y respuesta para endpoints (EDR) administrados que Huntress ha visto en lo que va del año, pero casi el 99% de esas detecciones fueron de alta severidad. Las publicaciones en redes sociales siguen mostrando que muchos usuarios caen a diario en la estafa de ClickFix.
Basta con que se pegue un solo comando malicioso en un cuadro Ejecutar para abrir la puerta a infostealers, herramientas de acceso remoto, ransomware u otro software malicioso. Los resultados pueden ser devastadores, y pueden llevar a pérdidas financieras y, potencialmente, al compromiso de toda una empresa. Pero así como aprendimos a mirar a ambos lados antes de cruzar la calle, aprenderemos a no hacer lo que un cuadro de diálogo en una página web nos pida, solo porque lo pida. Un gramo de escepticismo vale más que horas de remediación.
Huntress agregó los siguientes indicadores de compromiso a nuestro GitHub.
Indicadores de compromiso de red (IOCs)
Elemento | Descripción |
|---|---|
| URL de anuncio patrocinado: enlace malicioso alojado en un resultado patrocinado de Google |
| Marcadores/parámetros de clic en anuncios |
| Página de destino falsa con prueba CAPTCHA/ClickFix que suplanta un inicio de sesión de Amazon |
| URL alternativa de payload para macOS |
| Infraestructura del atacante: infraestructura Finger/.plan |
| Indicio del uso del protocolo Finger |
| Infraestructura del atacante |
| Infraestructura del atacante |
| Infraestructura del atacante |
| Infraestructura del atacante |
| URL de entrega de Timer6 |
| URL de la etapa V6 |
| URL del paquete Node |
| Dominio sin temática de barbacoa reportado por alojar paquetes de Node/stealer e integrado en el stealer. |
| IP de NetSupport fraudulenta |
| Indicio del uso de los protocolos de comunicación predeterminados del cliente NetSupport |
| URL de NetSupport fraudulenta |
Indicadores de compromiso binarios (IOC)
Elemento | Descripción |
|---|---|
| Archivo legítimo descargado y usado para proporcionar ipyw32.exe; el informe indica que se escribió en Temp con una extensión .pdf antes de extraerse. |
SHA256: | Script de Python ofuscado con sustitución Base64/cirílica y una capa de shellcode protegida con XOR. |
| Cuerpo de respuesta V6 descifrado con RC4 |
| Runtime de Node y artefactos de script/paquete asociados; el intérprete puede ser legítimo, mientras que el script/paquete se describe como malicioso. |
| Archivo ZIP del runtime de Node |
| Ejecutable del cliente NetSupport y ruta de C2 reportada. El ejecutable es un binario de RMM legítimo y firmado, usado en un contexto malicioso. |
. SHA256: | Payload de Lumma Stealer, descifrado |
. SHA256: | Payload de Lumma Stealer, descifrado |
. SHA256: | Payload de Lumma Stealer, descifrado |
. SHA256: | Payload de Lumma Stealer, descifrado |
. SHA256: | Payload de Lumma Stealer, descifrado |