Un pequeño error tipográfico en el nombre del paquete — y StubMaker se lleva contraseñas, billeteras y sesiones de Telegra

Un pequeño error tipográfico en el nombre del paquete — y StubMaker se lleva contraseñas, billeteras y sesiones de Telegra

¿Te suenan loadashjs, typescirpt-cli o axois-http? Exactamente para eso fue diseñado StubMaker.

image

Los desarrolladores fueron atacados a través de paquetes falsos en dos repositorios populares al mismo tiempo: los atacantes publicaron 16 bibliotecas maliciosas en RubyGems y otras 37 en npm, usando nombres con errores tipográficos que imitaban dependencias conocidas. La instalación de la trampa en Windows ejecutaba StubMaker, un robador de datos que recopilaba contraseñas y sesiones activas de navegadores, información de tarjetas bancarias, monederos de criptomonedas, frases semilla y archivos de Telegram Desktop. El análisis de ambas oleadas mostró infraestructura común, el mismo cargador y el mismo módulo malicioso principal.

La primera parte de la campaña se detectó el 15 de agosto en RubyGems. Para su difusión usaron el registro de paquetes por errores tipográficos: el atacante registra un paquete con un nombre muy parecido al de una biblioteca popular y cuenta con que un desarrollador se equivoque al escribir el comando de instalación o al elegir una dependencia. A StubMaker se le asociaron 16 nombres: ubnuler, ubnlder, ri18nr, reaker, rakier, orakw, joxn, ise18n, ioe18n, ie18u, iai8n, i1l8n, i18om, activesupmport, brumdler y brundlef. Los nombres imitaban, entre otros, a Bundler, i18n, Rake y Active Support.

Los autores de la campaña aprovecharon además una característica de RubyGems que permite volver a ocupar un nombre de paquete liberado. Al menos brumdler y brundlef se publicaron inicialmente desde una cuenta, luego se eliminaron y los nombres pasaron a otras cuentas de los atacantes. Si todas las versiones de un gem se eliminan y el nombre vuelve a estar disponible, otro usuario puede registrarlo. Por eso la eliminación de una biblioteca maliciosa no cierra necesariamente ese nombre para siempre.

Otro recurso ayudaba a ocultar la relación entre los paquetes. En la especificación de RubyGem el campo authors contiene texto libre y no actúa como un registro identificador verificado del propietario. El autor del paquete puede indicar allí un nombre que no coincide con la cuenta usada para publicar. Los atacantes ponían distintos nombres de autores en varias bibliotecas, aunque subían los paquetes desde las mismas cuentas. La documentación oficial de RubyGems describe el campo authors como un dato de metadatos en la especificación del gem, junto con nombre, versión, descripción y dirección de correo electrónico.

El código malicioso se ejecutaba ya durante la instalación del paquete Ruby. Se aprovechaba del archivo extconf.rb, destinado a preparar extensiones nativas. Normalmente RubyGems ejecuta extconf.rb para comprobar la disponibilidad de funciones y bibliotecas necesarias y generar un Makefile para compilar la extensión. La guía oficial de RubyGems describe exactamente ese flujo de trabajo.

StubMaker reemplazaba la compilación legítima por una ficticia. extconf.rb generaba un Makefile con objetivos vacíos all, install y clean, además de plantillas para Unix y Windows. Los scripts no compilaban el componente útil, sino que terminaban sin error, de modo que RubyGems recibía un informe de compilación exitosa. Paralelamente, el instalador detectaba el sistema operativo y ejecutaba la cadena maliciosa. El nombre StubMaker se relaciona precisamente con la creación de esas plantillas, que ocultaban la verdadera actividad del script de instalación.

En Windows, el código Ruby descargaba desde GitHub un archivo de alrededor de 22 MB. La dirección se ocultaba previamente usando Base64. El main.exe obtenido contenía un cargador en Rust, dentro del cual había un módulo ejecutable cifrado de aproximadamente 11 MB escrito en Go. No era necesario descargar el robador principal por separado: el cargador descifraba el PE embebido, verificaba la firma MZ, localizaba las funciones necesarias de Windows y colocaba el programa en memoria.

El módulo principal, identificado como wincfg, se centraba sobre todo en datos de navegadores basados en Chromium. Entre los objetivos estaban Google Chrome, Microsoft Edge, Brave, Opera, Opera GX, Vivaldi, Yandex Browser, Avast Secure Browser, AVG Secure Browser y CCleaner Browser. El malware buscaba credenciales guardadas, cookies y tokens de sesiones activas, el historial de navegación, información de extensiones y números de tarjetas de pago.

Para acceder a los datos protegidos de los navegadores, StubMaker usaba la DLL abe_payload.dll. La biblioteca ayudaba a sortear la protección conocida como cifrado vinculado a la aplicación (ABE). Google aplica este mecanismo en Chrome para dificultar el robo de secretos locales por otros procesos de Windows: las claves protegidas se ligan a la aplicación autorizada para descifrarlas. StubMaker inyectaba su propia DLL en el proceso del navegador e intentaba obtener los datos necesarios desde ese contexto de confianza. Google confirma el uso de App-Bound Encryption como medida para proteger frente al robo de datos del navegador por programas maliciosos.

Los datos de criptomonedas los recogía un conjunto de funciones aparte. El código buscaba monederos de software y extensiones de navegador como MetaMask, Coinbase Wallet, Phantom, Solflare, Exodus, Electrum, Bitcoin, Litecoin, Dogecoin, Monero, Atomic, Guarda y Trezor Suite. Además, el robador inspeccionaba archivos de texto y JSON en busca de secuencias que se parecieran a frases de recuperación y contrastaba las palabras encontradas con el vocabulario BIP-39. Los resultados se grababan en los archivos wallets.txt y seeds.txt. En las muestras analizadas no se encontró un mecanismo de transferencia automática de criptomonedas. StubMaker robaba datos que permitían acceder al monedero posteriormente.

Telegram Desktop también estaba entre los objetivos. El robador buscaba el directorio tdata, donde el cliente guarda los datos locales de sesión, y comprobaba las rutas de instalación habituales. Al mismo tiempo, el malware recopilaba el nombre de usuario de Windows, el nombre del equipo, la versión del sistema operativo, información del procesador y de la tarjeta gráfica, la cantidad de memoria RAM y la IP pública. Para determinar la dirección externa se usaba el servicio api.ipify.org.

Los archivos recopilados los empaquetaba en un ZIP protegido con contraseña y los subía a Gofile. Tras la carga, el malware obtenía el enlace al archivo y lo enviaba al operador a través de dresslee.com por HTTP sin cifrar. Junto con el enlace se enviaba un resumen del equipo infectado y del número de contraseñas, cookies, entradas de historial y datos de criptomonedas encontrados. Las muestras analizadas no intentaban persistir mediante servicios de Windows, el programador de tareas, claves de inicio automático ni la carpeta Startup. La campaña estaba diseñada para robar información inmediatamente después de instalar la dependencia comprometida.

Al día siguiente se detectó la segunda parte de StubMaker. El 16 de agosto aparecieron en npm 37 paquetes con nombres parecidos a Axios, Chalk, Commander, Lodash, TypeScript y React. No se comprometieron los proyectos legítimos: los atacantes publicaron paquetes duplicados independientes. Entre los ejemplos estaban axois-http, chalk-core, comander-cli, loadashjs, typescirpt-cli y raectjs. Los autores cambiaban el orden de las letras, omitían caracteres y añadían sufijos -core, -lib o -cli para que el nombre pudiera confundirse con una biblioteca auxiliar de un proyecto conocido.

Los 37 paquetes de npm recibieron la versión 1.0.0 y contenían un guion malicioso postinstall.js prácticamente idéntico. npm ejecuta automáticamente los guiones postinstall tras instalar un paquete, de modo que el desarrollador no necesitaba importar la biblioteca ni ejecutar una función por separado: bastaba con instalar la dependencia.

Las fases iniciales para RubyGems y npm diferían. La variante de Ruby usaba extconf.rb y guardaba la dirección del cargador en una cadena Base64. La variante de npm se ejecutaba mediante postinstall y ocultaba la dirección mediante XOR con una clave fija repetida. Tras descifrar la dirección, ambas cadenas pasaban al mismo cargador para Windows.

Los paquetes de npm también consideraban Windows Subsystem for Linux. Los PE destinados a Windows no se ejecutan en Linux y macOS, pero WSL se trataba por separado: el guion de instalación, desde el entorno Linux, invocaba el powershell.exe de Windows, descargaba main.exe y ejecutaba el cargador en el sistema principal. Por tanto, trabajar dentro de WSL no protegía al desarrollador frente a la versión de StubMaker para Windows.

RubyGems y npm mostraron velocidades de publicación de paquetes maliciosos muy distintas. Las bibliotecas Ruby aparecían de forma secuencial durante dos días: tras eliminar una tanda, el operador cambiaba de cuenta y continuaba publicando. El grueso de los paquetes de npm se subió en aproximadamente ocho minutos desde cinco cuentas. Distribuir los paquetes entre varios perfiles temporales reducía la dependencia de la campaña de una sola cuenta, aunque npm detectó y eliminó rápidamente todo el grupo.

Un servidor común vinculó definitivamente ambas oleadas. RubyGems y npm enviaban datos a 193.70.34.101:20099/vote, consultaban el mismo Release de GitHub para obtener main.exe y descargaban un archivo con idéntico hash SHA-256. Dentro del cargador había un robador en Go idéntico. De este modo, un único operador distribuía la misma herramienta maliciosa a través de dos ecosistemas de paquetes.

No se detectó autorreplicación en StubMaker. El malware no infectaba bibliotecas legítimas, no secuestraba cuentas de sus autores ni publicaba copias por sí mismo. Para comprometerse era necesaria la instalación de uno de los paquetes trampa en Windows o en WSL.

Al momento de la publicación, los paquetes detectados se eliminaron de RubyGems y npm, y la cuenta de GitHub desde la que se descargaba el cargador quedó inaccesible. Se recomienda aislar los equipos donde la dependencia maliciosa llegó a instalarse, cerrar las sesiones activas de navegadores y de Telegram y cambiar las contraseñas desde otro dispositivo de confianza. Si las frases semilla se almacenaron en el equipo infectado, es más seguro considerar comprometidos los monederos correspondientes y transferir los fondos a nuevas direcciones creadas en un entorno limpio.