PhantomBot: Del robo de credenciales a la botnet.

PhantomBot: Una campaña de typosquat que pasó del robo de credenciales a un kit de botnet llave en mano.

TL; DR

Un único editor npm, deadcode09284814ha llevado a cabo una campaña de typosquat contra el legítimo axios y chalk-template paquetes desde mediados de mayo de 2026.

La campaña comenzó como un ladrón de credenciales y billetera convencional, exfiltrando datos a un Túnel HTTPS de Serveo.

On 2026-05-17, en el que axois-utils:1.0.9, el operador cambió la carga útil por completo: la misma estructura triple de gancho de instalación, el mismo editor, el mismo nombre de paquete.

Pero el script de instalación ahora recluta a una botnet DDoS multiplataforma.

La carga útil habla de un localhost.run Crea un túnel y acepta comandos de inundación, convirtiendo los entornos infectados en parte de una botnet con capacidad para realizar ataques DDoS.

El operador incluso envió el binario del servidor C2 Dentro del archivo comprimido, se observa una clara escalada desde el robo de credenciales hasta la infraestructura activa de una red de bots.

Dos paquetes, cuatro versiones aún activas en el registro, y un operador que ahora ejecuta ambos módulos en paralelo.

Gravedad: alta.

Titular COI Cualquier versión de axois-utils o chalk-tempalte del editor deadcode09284814

El ataque: cómo funciona

La campaña se basa en un andamiaje de entrega deliberadamente aburrido: dos nombres de paquetes con errores tipográficos, una letra diferente de paquetes con cientos de millones de descargas semanales (axios, plantilla de tiza), y triple instalación hooks que garantizan la ejecución. Lo interesante es lo que el andamio acarreos — y el hecho de que el operador cambió la carga sin cambiar nada más.

El andamio compartido

Cada versión publicada de ambos paquetes declara el mismo ciclo de vida de tres etapas. hooks in package.json:

"scripts": {    "preinstall":  "node <payload>.js",    "install":     "node <payload>.js",    "postinstall": "node <payload>.js"  } 

Listar la carga útil en los tres hooks es excesivo postinstalación por sí solo se ejecutaría en un modo predeterminado npm instalarLa elección importa: npm install –ignore-scripts omite scripts, pero varios flujos de trabajo comunes (restauraciones de caché de CI que vuelven a ejecutar el ciclo de vida) hooks de forma selectiva, o desarrolladores que solo auditan postinstalación) hacer una declaración triplemente redundante es la apuesta más segura para el atacante.

plantilla de tiza agrega un segundo mecanismo: declara axois-utils:^1.0.7 como un entorno de ejecución dependencia. Instalando el typosquatted plantilla de tiza Por lo tanto, también incluye el error tipográfico asociado, y ambas cargas útiles se ejecutan. Los dos paquetes forman un conjunto coordinado, no son listados independientes.

Fase A: robo de credenciales/billeteras (15/05/2026 → actualidad)

La fase A es la carga útil original. El cargador es un corto postinstall.js que apunta a un túnel inverso HTTPS de Serveo:

// chalk-tempalte/postinstall.js:11-13  const C2_HOST = "f04a273bd84c0622-80-200-28-28.serveousercontent.com";  const C2_PORT = 443;  const C2_PATH = '/collect'; 

El subdominio Serveo codifica la IP de destino (80.200.28.28) directamente en el nombre de host, una convención reconocible para ese servicio. El operador rota el prefijo de subdominio aleatorio entre versiones para evadir las listas negras de dominios ingenuas, pero la IP subyacente nunca cambia.plantilla de tiza: 1.0.14 usado 8a3e818ea8f11186-80-200-28-28…; 1.0.16 / 1.0.19 / 1.0.20 uso f04a273bd84c0622-….)

postinstall.js manos fuera de phantom.js, un módulo “recolector” empaquetado de 7,667 líneas. phantom.js pasea al anfitrión para:

claves privadas SSH (~/.ssh/*)
.npmrc contenidos y cualquier npm_* tokens de entorno
Archivos de credenciales de AWS, GCP y Azure
Expresión regular para token de acceso personal de GitHub (ghp_*, gho_*, ghu_*, ghs_*)
Dispositivos de monedero de criptomonedas para Bitcoin, Exodus, Electrum, Monero, Litecoin, Dogecoin, Zcash, Dash
Un recursivo .env* ensayar ~/projects, ~/dev, ~/code, ~/workspacey el cwd de instalación
Historias de Shell y el completo process.env

El paquete se envía mediante POST al túnel Serveo en /recolectarNo hay ofuscación, ni lógica anti-máquinas virtuales, ni puesta en escena: la apuesta del operador está en el volumen y la velocidad.

Fase B: reclutamiento de PhantomBot DDoS (17/05/2026, solo para axois-utils:1.0.9)

La fase B reemplaza phantom.js + postinstall.js con un único archivo llamado distrube.js (el error tipográfico es del operador). La estructura de triple gancho en package.json permanece sin cambios; el paquete conserva el mismo nombre, alcance y patrón de actualización de versión. A simple vista, axois-utils:1.0.9 parece una actualización menor de la versión 1.0.6. Internamente, se trata de una familia de malware diferente.

perturbar.js Se abre con un bloque de configuración que especifica la marca propia del operador:

// axois-utils-1.0.9/distrube.js:11-15
// Use your localhost.run HTTPS URL (the tunnel handles HTTP internally)
const C2_HOST = 'b94b6bcfa27554.lhr.life'; // Your localhost.run tunnel
const C2_PORT = 443; // HTTPS port - tunnel handles SSL
const BOT_ID = `${os.hostname()}_${Date.now()}_${crypto.randomBytes(4).toString('hex')}`;

Los comentarios van dirigidos a un futuro operador que ejecute el kit («Utilice su URL HTTPS localhost.run»). Esto, sumado a lo que se incluye con el cliente del bot, indica que no se trata simplemente de una carga útil para la víctima, sino del kit completo.

El flujo:

  1. Persistencia se ejecuta primero. El script se instala de tres maneras diferentes por sistema operativo (registro Ejecutar + Carpeta de inicio + schtasks en Windows; crontab + phantom-bot.service unidad systemd + .bashrc/.zshrc agregar + /etc/rc.local en Linux; LaunchAgent com.phantom.bot.plist en macOS). El nombre del servicio de persistencia y la etiqueta LaunchAgent son ambos robot fantasma / com.phantom.bot, que es también de donde proviene el nombre de la campaña.
  2. Información del sistema exfil Se ejecuta una sola vez: una solicitud POST de huella digital a b94b6bcfa27554.lhr.life:443/collect que incluye nombre de host, plataforma, arquitectura, nombre de usuario, CPU/RAM, interfaces de red, process.env, directorio de trabajo actual, directorio de inicio, versión del nodo e IP pública. Esto es mucho menos agresivo que la Fase A: sin SSH, sin monederos, sin recursión de .env. La función del bot es registrarse, no robar.
  3. bucle de latido del corazón Se abre una solicitud HTTPS POST cada 30 segundos a b94b6bcfa27554.lhr.life:443/. El User-Agent es PhantomBot/1.0. La verificación TLS está explícitamente deshabilitada (rejectUnauthorized: false). La respuesta C2 se analiza como JSON con el formato {type, target, port, duration, threads, method} y se envía.
  4. arsenal de inundaciones está conectado a seis comandos:
Tipo de comando Módulo Notas
de ping Respuesta en vivo El bot se identifica
http Inundación HTTP Inundación de solicitudes de capa 7
https inundación HTTPS Igual que http, envuelto en TLS.
tcp Inundación de TCP Spam de carga útil aleatoria de 65 KB
udp Inundación UDP Paquetes UDP de 65,507 bytes
rápido Ataque DoS de reinicio rápido HTTP/2 La técnica CVE-2023-44487 de 2023

Los cinco módulos de inundación toman un dirigidos, Puerto, duración, y threads Argumento: el bot es un programa genérico de envío masivo de correos electrónicos a sueldo, no dirigido a ninguna víctima en particular. La lista de víctimas del operador reside en el servidor C2, no en el paquete.

Novedades: el binario C2 distribuido

La fase A tiene una forma familiar: robo de credenciales, gancho de instalación, C2 tunelizado por el proveedor. La fase B es también una forma familiar: las botnets DDoS han sido un elemento fijo de los paquetes npm maliciosos durante años. Lo inusual es que el operador envió el lado del servidor del kit dentro del archivo tarball de npm:

  • c2 — un binario Go ELF compilado de 4 megabytes
  • c2.go — el código fuente Go de 426 líneas para ese binario

Ninguno de los archivos es invocado por ningún gancho de instalación. No forman parte de la carga útil de la víctima. Se encuentran en el directorio del paquete, al igual que un archivo de documentación. La interpretación más plausible es que el operador subió su árbol de trabajo de desarrollo a npm sin revisar la lista de archivos —un verdadero fallo de seguridad operativa— y lo que se envió fue el kit completo de doble vía: el cliente que ejecuta la víctima y el servidor que ejecuta el operador.

Esta es la parte de la historia que justifica el encuadre del "kit de botnet llave en mano". Cualquiera que haya descargado axois-utils:1.0.9 Antes de que se produzca la eliminación, no solo tienen una muestra de la víctima, sino que también disponen de un servidor C2 operativo.

El punto de inflexión, en una sola frase.

Mismo editor, mismos nombres de paquetes, mismo andamiaje de triple gancho, misma marca "fantasma", pero La carga útil cambió el modelo de monetización de la noche a la mañana.: desde “cosechar Secretos que puedo revender” hasta “alquilar capacidad de inundación que puedo arrendar”. Las TTP de tiempo de instalación que los defensores deben vigilar son casi idénticas en ambas fases; defensas basadas en firmas vinculadas a las cadenas de ruta de billetera de la Fase A o a phantom.jsEl colector de 7,667 líneas se habría perdido por completo la Fase B.

Fecha (UTC) Eventos
2026-05-15 Primera publicación: axois-utils:1.0.4 (Configuración de prueba LAN, plataforma de desarrollo en 192.168.129.19)
2026-05-15 axois-utils:1.0.6 publicado — Fase A C2 intercambiada a 80.200.28.28 a través del túnel Serveo; el comentario de origen // Change to '80.200.28.28' for public confirma el intercambio dev→prod
2026-05-16 chalk-tempalte:1.0.14 y 1.0.16 publicado — cargador encadenado declarando axois-utils:^1.0.7 como dependencia de tiempo de ejecución; subdominio de Serveo rotado
2026-05-16 Se descubrió una campaña de fase A durante un escaneo rutinario de npm; se aplicaron veredictos de confirmación de actividad maliciosa.
2026-05-17 axois-utils:1.0.9 publicado — pivote de carga útil: reclutamiento de DDoS de PhantomBot a través del túnel localhost.run; lado del operador c2 binario y c2.go Fuente enviada en el archivo tar.
2026-05-17 chalk-tempalte:1.0.19 y 1.0.20 Publicado — todavía en fase A (ladrón); el operador ahora ejecuta ambos módulos en paralelo
2026-05-17 Descubrimiento de la Fase B durante el escaneo de rutina; los veredictos se aplican a todos. 2026-05-17 versiones
(en marcha) Informes de retirada pendientes; los cuatro paquetes publicados siguen disponibles en el registro en el momento de redactar este informe.

Indicadores de compromiso

Paquetes

Ecosistema PREMIUM Source-Connect
npm axois-utils (typosquat de axios) 1.0.4, 1.0.6, 1.0.9
npm chalk-tempalte (tipografía abreviada de chalk-template) 1.0.14, 1.0.16, 1.0.19, 1.0.20

Identidad del autor

Campo Valor
editor npm deadcode09284814
Correo electrónico del editor phantomdeadcode@tutamail.com
SCM verificación ninguna

Mando y control

Fase Punto final Logística de transporte
A f04a273bd84c0622-80-200-28-28.serveousercontent.com:443/collect Túnel HTTPS de Serveo
A 8a3e818ea8f11186-80-200-28-28.serveousercontent.com:443/collect Túnel HTTPS de Serveo (versión anterior)
A 80.200.28.28:443/collect Punto final VPS subyacente
B b94b6bcfa27554.lhr.life:443/ localhost.run túnel inverso HTTPS

Resúmenes de archivos (SHA-256)

Archivo SHA-256 Notas
c2 (Go ELF, 4 MB) 165fa92d237fd017c227d00da06ab788212a62be94bf61e95df2d22d00377ef2 Servidor C2 del lado del operador, enviado dentro axois-utils:1.0.9
c2.go (426 líneas) 7d0ae79fdb1e9968f3323a3712b624643a782ba3efb2cf3a2cb9c4c5513cea30 Obtén el código fuente del binario C2
distrube.js 308b15c023088a7188dea4ef609010ac2493eb4c365b103053d7621a9ca5b935 Cliente bot de la fase B
phantom.js (chalk-tempalte:1.0.19) 9e380ec88d3ccf3929e1a104e3b868d4d7b59ca189a8a431a54e9f3357dfdd81 Recopilador de credenciales/billeteras de la Fase A
phantom.js (chalk-tempalte:1.0.20) d1c9e3f296ee9f7d5032f73f9c504cede50334bc14c394055fd5cb9c3a6e08b3 Colector de fase A (variante 1.0.20)
postinstall.js (chalk-tempalte:1.0.19 = 1.0.20) ffba9bdd6793edd5b38e12900252c1813a693f59c25af51c3b658cf3f27b6162 Cargador de fase A, idéntico byte a byte en ambas versiones.

Atribución y motivación

Realizamos un seguimiento de esta campaña como FantasmaBot, tomando la propia marca del operador de la Agente de usuario: PhantomBot/1.0 encabezado de latido del corazón, el phantom-bot.service unidad systemd, la com.phantom.bot etiqueta LaunchAgent y la código muerto fantasma@ Dirección de correo electrónico. El operador utiliza este nombre de forma consistente en al menos cuatro documentos.

Catálogo de señales

  • Publisher - deadcode09284814 en npm. Cuenta de un solo manejador, correo electrónico desechable de Tutamail, no SCM Verificación. No hay historial de publicaciones previas más allá de esta campaña.
  • Reutilización de marcas — “fantasma” aparece en el correo electrónico del editor, en el nombre del archivo del recopilador de la Fase A (phantom.js), en el nombre del servicio de persistencia de la Fase B (phantom-bot.service), en la etiqueta LaunchAgent (com.phantom.bot), y en el User-Agent del bot (PhantomBot/1.0).
  • Infraestructura — Un único VPS en 80.200.28.28 frentes Fase A a través de rotación de subdominios Serveo; la Fase B se mueve a un localhost.run túnel inverso (b94b6bcfa27554.lhr.lifeAmbos servicios de proveedores son gratuitos y solo requieren SSH saliente por parte del operador, lo que es coherente con las configuraciones de bajo presupuesto y baja seguridad operativa.
  • Estilo de código — JavaScript puro en todo el texto; sin ofuscación, sin codificación de cadenas, sin comprobaciones anti-VM. Los nombres de las variables son descriptivos (robarSystemInfo, ejecutarComando, httpInundación). Comentarios en perturbar.js Dirigirse directamente a un futuro operador ("Utilice su URL HTTPS localhost.run"), lo que sugiere que el archivo estaba destinado a ser redistribuido como un kit, no utilizado por un solo atacante.
  • Desliz de OpSec — El archivo tarball de la Fase B incluye tanto el cliente bot como el servidor C2 del lado del operador (c2 ELF + c2.go fuente). Esto es consistente con un operador que subió su árbol de trabajo a npm sin auditar la lista de archivos. O el operador no tiene experiencia, o el kit es tratado Se distribuirá públicamente y el binario C2 forma parte del producto.
  • Autoconfirmación - axois-utils:1.0.4 contiene el comentario fuente // Cambiar a '80.200.28.28' para público En la línea 12, se confirma la progresión de desarrollo/preproducción/producción que los operadores suelen negar.

Necesidades

La carga útil de la Fase A es un robo financiero directo: credenciales, claves en la nube, tokens de GitHub y billeteras de criptomonedas tienen mercados de reventa líquidos. La Fase B también es financiera, pero indirecta: los servicios de DDoS por encargo ("booter") alquilan capacidad de inundación por minuto, y los bots como el que se envía aquí son el inventario que utilizan esos servicios. El latido de 30 segundos, el genérico dirigidos/Puerto/duración esquema de comando y el arsenal de inundación de cinco protocolos son los standard producto de un operador de booters.

Ejecutar ambos módulos en paralelo — plantilla de tiza: 1.0.19 y 1.0.20 continuar enviando al ladrón mientras axois-utils:1.0.9 El envío del bot sugiere que el operador está cubriendo sus flujos de ingresos en lugar de abandonar la Fase A. El giro es un adición, no un reemplazo.

Lo que no estamos afirmando

No hemos podido confirmar una identidad real detrás de la deadcode09284814 No atribuimos esta campaña a ningún actor, grupo o país en particular. La marca "fantasma" es lo suficientemente consistente en todos los artefactos como para sugerir un único operador, pero el envío del binario C2 en formato de kit deja abierta la posibilidad de que futuros paquetes de identificadores no relacionados reutilicen el mismo código.

Generar impacto

Los objetivos legítimos para sentadillas axios y plantilla de tiza son ampliamente utilizados en el ecosistema de JavaScript; axios solo se encuentra entre los treinta paquetes npm más descargados. Los nombres typosquat están a una pulsación de tecla de los reales (axoisaxios, plantillaplantilla), y ambas son faltas de ortografía lingüísticamente plausibles.

No pudimos obtener estadísticas de descarga confiables para las versiones maliciosas antes de su eliminación: npm no conserva los recuentos de descarga por versión después de que un paquete se despublica, y npms.ioLos proxies de estilo son ruidosos a esta escala. Cualquier organización cuyo archivo de bloqueo se resuelva en un paquete llamado axois-utils or plantilla de tiza del editor deadcode09284814 debe tratarse como comprometido: rotar cada credencial presente en proceso.env En el host afectado, audite los vectores de persistencia por sistema operativo (consulte “Qué deben hacer los defensores” a continuación) y elimine la dependencia.

Patrones emergentes

Esta campaña ejemplifica un cambio que hemos observado en varios incidentes recientes de npm: El andamio con gancho de instalación es un activo duradero.; la carga útil es intercambiable. El mismo editor, el mismo paquete, el mismo preinstalación / instalar / postinstalación triple, e incluso la misma cadencia de actualización de versión: lo único que cambió entre axois-utils:1.0.6 y axois-utils:1.0.9 era el archivo el hooks ejecutar. Detección basada en firmas vinculada a la carga útil de la Fase A (cadenas de ruta de billetera, phantom.jsEl recolector de 7,667 líneas de Serveo C2 habría marcado las tres primeras versiones y se habría perdido por completo la Fase B.

El mismo patrón se observa en otras campañas de 2026 que hemos analizado: un único operador con una estructura estable, que alterna entre el robo de credenciales, clientes que hacen trampa en exámenes, la extracción de datos mediante bots de Telegram y, ahora, el reclutamiento para ataques DDoS. Los defensores que confían en las firmas de la carga útil seguirán perdiendo la segunda ronda de cada campaña.

El corolario es que Los TTP de instalación son la mejor señal.Declaraciones de gancho de instalación triples, scripts de instalación que importan https or proceso_niño, instalar scripts que escriban en las carpetas de inicio del usuario e instalar scripts que resuelvan nombres de host en servicios de túnel inverso gratuitos (Serveo, localhost.run(como ngrok y cloudflared) son poco comunes en paquetes legítimos y frecuentes en paquetes maliciosos.

Qué deben hacer los defensores

  • Auditoría de archivo de bloqueo. Buscar cada Paquete-lock.json / hilo.lock / pnpm-lock.yaml en su organización para las cadenas exactas axois-utils y plantilla de tizaConsidera cualquier partido como un compromiso.
  • Rotar secretos en los huéspedes afectados. Fase A: credenciales SSH, nube, GitHub, npm y billetera recopiladas masivamente. Suponga que todas las credenciales que alguna vez estuvieron presentes en proceso.env, ~ / .ssh, ~/.aws, ~ / .npmrc, ~ / .config, o cualquier .env* El archivo en el host afectado está expuesto.
  • Eliminar la persistencia (Fase B). En Windows, eliminar HKCU\Software\Microsoft\Windows\VersiónActual\Ejecutar\ActualizaciónDelSistema, eliminar %APPDATA%\Microsoft\Windows\Menú Inicio\Programas\Inicio\actualización-del-sistema.bat, y schtasks /delete /tn SystemUpdate /f. En Linux, crontab -e y quitar @reboot nodo …, systemctl –user disable –now phantom-bot.service luego borrar ~/.config/systemd/user/phantom-bot.service, fregar .bashrc / .zshrc / /etc/rc.local. En macOS, launchctl unload ~/Library/LaunchAgents/com.phantom.bot.plist Luego, elimine el archivo plist.
  • Bloquea los hosts C2. Agregue los cuatro puntos finales C2 de la tabla IOC a su lista de bloqueo de salida. *.serveousercontent.com y *.lhr.life Se puede bloquear por completo si su entorno no tiene un uso legítimo para los servicios de túnel inverso.
  • Búsqueda por TTP de tiempo de instalación, no la carga útil. Entradas de archivo de bloqueo de inventario cuyas package.json declara preinstalación, instalar, y postinstalación Todos apuntan al mismo script. Compruébelo con la antigüedad del paquete y el estado de verificación del editor. Este patrón es poco común en paquetes legítimos y es la señal más fiable que PhantomBot reutiliza.
  • Auditoría para el binario C2. Cualquiera que haya descargado axois-utils:1.0.9 tiene el servidor C2 del operador (c2 ELF, sha256 165fa92d…) en el disco. Escanee las cachés y los almacenes de artefactos de CI. El binario está inactivo por sí mismo, pero su presencia en una estación de trabajo es una prueba inequívoca de que el paquete se instaló.

Línea de cierre

El mismo operador, el mismo paquete y el mismo método de instalación pueden generar amenazas completamente diferentes en 48 horas. Presta atención a la estructura, no al contenido.

sca-tools-software-herramientas-de-analisis-de-composicion
Priorice, solucione y proteja sus riesgos de software
Obtén tu cuenta gratuita.
Sin tarjeta de crédito.

Asegure el desarrollo y entrega de software

con la suite de productos Xygeni