TL; DR
Un únic editor npm, deadcode09284814, ha dut a terme una campanya typosquat contra la legítima axios i chalk-template paquets des de mitjans de maig de 2026.
La campanya va començar com un lladre convencional de credencials i carteres, exfiltrant dades a un Túnel HTTPS de Serveo.
On 2026-05-17, Amb axois-utils:1.0.9, l'operador va intercanviar completament la càrrega útil: la mateixa estructura de triple instal·lació-hook, el mateix editor, el mateix nom de paquet.
Però l'script d'instal·lació ara és un recluta de botnets DDoS multiplataforma.
La càrrega útil parla a un localhost.run túnel i accepta ordres d'inundació, convertint els entorns infectats en part d'una botnet compatible amb DDoS.
L'operador fins i tot va enviar el Binari del servidor C2 dins del tarball, que mostra una clara escalada des del robatori de credencials fins a la infraestructura de botnet activa.
Dos paquets, quatre versions encara actives al registre i un operador que ara executa els dos mòduls en paral·lel.
Gravetat: alta.
L'atac: com funciona
La campanya es basa en una bastida de lliurament deliberadament avorrida: dos noms de paquets typosquat, amb una lletra diferent dels paquets amb centenars de milions de descàrregues setmanals (axis, plantilla de guix) i instal·lació triple hooks que garanteixen l'execució. El que és interessant és què fa la bastida porta — i el fet que l'operador va canviar la càrrega sense canviar res més.
La bastida compartida
Cada versió publicada d'ambdós paquets declara els mateixos tres cicles de vida hooks in paquet.json:
Llistant la càrrega útil sota els tres hooks és excessiu — postinstal·lació sol s'executaria per defecte npm instal·larL'elecció importa: instal·lació de npm –ignore-scripts omet els scripts, però diversos fluxos de treball comuns (restauracions de memòria cau de CI que tornen a executar el cicle de vida hooks selectivament, o desenvolupadors que només auditen postinstal·lació) fan que una declaració triplement redundant sigui l'aposta més segura per a l'atacant.
plantilla de guix afegeix un segon mecanisme: declara axois-utils:^1.0.7 com a temps d'execució dependència. Instal·lació del typosquatted plantilla de guix per tant, també extreu el typosquat germà, i ambdues càrregues útils s'executen. Els dos paquets són un parell coordinat, no llistats independents.
Fase A — lladre de credencials / carteres (15-05-2026 → present)
La fase A és la càrrega útil original. El carregador és curt postinstal·lació.js que apunta a un túnel invers HTTPS de Serveo:
El subdomini Serveo codifica la IP de destinació (80.200.28.28) directament al nom de l'amfitrió, una convenció recognoscible per a aquest servei. L'operador rota el prefix aleatori del subdomini entre versions per evadir les llistes de bloqueig de dominis ingènues, però la IP subjacent no es mou mai. (chalk-template:1.0.14 usat 8a3e818ea8f11186-80-200-28-28…; 1.0.16 / 1.0.19 / 1.0.20 ús f04a273bd84c0622-….)
postinstal·lació.js mans lliures a phantom.js, un mòdul "col·leccionista" inclòs en un paquet de 7,667 línies. phantom.js passeja l'amfitrió per:
Claus privades SSH (~/.ssh/*) |
.npmrc continguts i qualsevol npm_* fitxes d'entorn |
| Fitxers de credencials d'AWS, GCP i Azure |
Expressió regular del testimoni d'accés personal del GitHub (ghp_*, gho_*, ghu_*, ghs_*) |
| Artefactes de moneders criptogràfics per a Bitcoin, Exodus, Electrum, Monero, Litecoin, Dogecoin, Zcash, Dash |
Un recursiu .env* caminar a través ~/projects, ~/dev, ~/code, ~/workspace, i la instal·lació cwd |
Històries de Shell i la totalitat process.env |
El paquet s'envia per POST al túnel Serveo a /collectNo hi ha ofuscació, ni lògica anti-VM, ni estadificació: l'aposta de l'operador és pel volum i la velocitat.
Fase B — Reclutament de PhantomBot DDoS (17-05-2026, només axois-utils:1.0.9)
La fase B substitueix phantom.js + postinstall.js per un únic fitxer anomenat distrube.js (l'error tipogràfic és de l'operador). L'estructura de triple ganxo a package.json no ha canviat; el paquet manté el mateix nom, abast i patró de canvi de versió. Des de fora, axois-utils:1.0.9 sembla una continuació menor de l'1.0.6. A dins, és una família de programari maliciós diferent.
distrube.js s'obre amb un bloc de configuració que anomena la marca pròpia de l'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')}`; |
Els comentaris estan dirigits a un futur operador que executi el kit (“Utilitzeu l'URL HTTPS localhost.run”). Això, a més del que s'inclou al costat del client del bot, indica que no es tracta només d'una càrrega útil de víctima, sinó del kit.
El flux:
- Persistència s'executa primer. L'script s'instal·la de tres maneres diferents per sistema operatiu (registre Correr + Carpeta d'inici + tasques a Windows; crontab + servei de bot fantasma unitat systemd + .bashrc/.zshrc afegir + /etc/rc.local a Linux; LaunchAgent com.phantom.bot.plist a macOS). El nom del servei de persistència i l'etiqueta LaunchAgent són tots dos robot fantasma / com.phantom.bot, que també és d'on prové el nom de la campanya.
- Exfil d'informació del sistema s'executa una vegada: una empremta digital POST d'un sol cop a b94b6bcfa27554.lhr.life:443/collect que conté el nom d'amfitrió, la plataforma, l'arquitectura, el nom d'usuari, la CPU/RAM, les interfícies de xarxa, process.env, cwd, homedir, la versió del node i la IP pública. Això és molt menys agressiu que la Fase A: sense SSH, sense carteres, sense recursió .env. La feina del bot és inscriure's, no robar.
- Bucle de batec del cor obre un POST HTTPS cada 30 segons a b94b6bcfa27554.lhr.life:443/. L'agent d'usuari és PhantomBot/1.0. La verificació TLS està explícitament desactivada (rejectUnauthorized: false). La resposta C2 s'analitza com a JSON del format {type, target, port, duration, threads, method} i s'envia.
- Arsenal d'inundacions està connectat a sis ordres:
| Tipus d'ordre | Mòduls | notes |
|---|---|---|
| fer ping | Resposta de Liveness | El bot s'identifica a si mateix |
| http | Inundació HTTP | Inundació de sol·licituds de capa 7 |
| https | Inundació HTTPS | Igual que http, encapsulat en TLS |
| tcp | Inundació de TCP | Correu brossa de càrrega aleatòria de 65 KB |
| udp | Inundació UDP | Paquets UDP de 65,507 bytes |
| ràpid | Restabliment ràpid de DoS per HTTP/2 | La tècnica CVE-2023-44487 del 2023 |
Els cinc mòduls d'inundació prenen una target, port, duradai fils argument: el bot és un "flooder" genèric a contracte, no dirigit a cap víctima en particular. La llista de víctimes de l'operador es troba al C2, no al paquet.
Novetats: el binari C2 enviat
La fase A té una forma familiar: robatori de credencials, ganxo d'instal·lació, C2 tunelitzat pel proveïdor. La fase B és També una forma familiar: les botnets DDoS han estat un element fix dels paquets npm maliciosos durant anys. El que és inusual és que l'operador va enviar el costat del servidor del kit dins del fitxer tar de npm:
- c2 — un binari Go ELF compilat de 4 megabytes
- c2.go — el codi font de Go de 426 línies per a aquest binari
Cap dels dos fitxers és invocat per cap ganxo d'instal·lació. No formen part de la càrrega útil de la víctima. Es troben al directori del paquet de la mateixa manera que ho faria un fitxer de documentació. La lectura més plausible és que l'operador va enviar el seu arbre de treball de desenvolupament a npm sense curar la llista de fitxers (una veritable fallada d'OpSec) i el que s'inclou és el kit complet de dues cares: el client que executa una víctima i el servidor que executa l'operador.
Aquesta és la part de la història que justifica la idea de "kit de botnet clau en mà". Qualsevol que hagi descarregat axois-utils:1.0.9 abans de l'eliminació no només té una mostra de víctima, sinó que també tenen un servidor C2 que funciona.
El pivot, en una frase
Mateix editor, mateixos noms de paquets, mateixa estructura de triple ganxo, mateixa marca "fantasma", però la càrrega útil va canviar el model de monetització de la nit al dia: des de "col·lectar secrets que puc revendre" fins a "llogar capacitat d'inundació que puc arrendar". Els TTP en temps d'instal·lació que els defensors haurien de vigilar són gairebé idèntics en ambdues fases; defenses basades en signatures lligades a les cadenes de ruta de cartera de la Fase A o a phantom.jsEl col·leccionista de 7,667 línies no hauria pogut completar la Fase B.
| Data (UTC) | esdeveniment |
|---|---|
| 2026-05-15 | Primera publicació: axois-utils:1.0.4 (Construcció de proves LAN, plataforma de desenvolupament a 192.168.129.19) |
| 2026-05-15 | axois-utils:1.0.6 publicat — Fase A C2 canviada a 80.200.28.28 via túnel Serveo; el comentari font // Change to '80.200.28.28' for public confirma l'intercanvi dev→prod |
| 2026-05-16 | chalk-tempalte:1.0.14 i 1.0.16 publicat — declaració de carregador encadenat axois-utils:^1.0.7 com a dependència en temps d'execució; el subdomini de Serveo ha estat rotat |
| 2026-05-16 | Campanya de fase A descoberta durant l'escaneig rutinari de npm; s'han aplicat veredictes de confirmació maliciosa. |
| 2026-05-17 | axois-utils:1.0.9 publicat — pivot de càrrega útil: reclutament DDoS de PhantomBot via túnel localhost.run; costat de l'operador c2 binari i c2.go codi font inclòs al fitxer tar |
| 2026-05-17 | chalk-tempalte:1.0.19 i 1.0.20 publicat — encara Fase A (lladre); l'operador ara executa els dos mòduls en paral·lel |
| 2026-05-17 | Descobriment de la Fase B durant l'exploració rutinària; els veredictes s'apliquen a tots 2026-05-17 versions |
| (en marxa) | Informes de retirada pendents; els quatre paquets publicats continuen disponibles al registre en el moment de la redacció. |
Indicadors de compromís
Paquets
| Ecosistema | paquet | versions |
|---|---|---|
| npm | axois-utils (typosquat d'axios) | 1.0.4, 1.0.6, 1.0.9 |
| npm | chalk-tempalte (typosquat de plantilla de guix) | 1.0.14, 1.0.16, 1.0.19, 1.0.20 |
Identitat de l'autor
| Camp | Valor |
|---|---|
| editor de npm | deadcode09284814 |
| Correu electrònic de l'editor | phantomdeadcode@tutamail.com |
| SCM verificació | cap |
Comandament i control
| Fase | Punt final | Transport. Porta el teu cotxe |
|---|---|---|
| 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ó anterior) |
| A | 80.200.28.28:443/collect | Punt final del VPS subjacent |
| B | b94b6bcfa27554.lhr.life:443/ | localhost.run túnel invers HTTPS |
Resums de fitxers (SHA-256)
| Dossier | SHA-256 | notes |
|---|---|---|
c2 (Vés a ELF, 4 MB) | 165fa92d237fd017c227d00da06ab788212a62be94bf61e95df2d22d00377ef2 | Servidor C2 del costat de l'operador, enviat a l'interior axois-utils:1.0.9 |
c2.go (426 línies) | 7d0ae79fdb1e9968f3323a3712b624643a782ba3efb2cf3a2cb9c4c5513cea30 | Anar al codi font per al binari C2 |
distrube.js | 308b15c023088a7188dea4ef609010ac2493eb4c365b103053d7621a9ca5b935 | Client de bot de fase B |
phantom.js (chalk-tempalte:1.0.19) | 9e380ec88d3ccf3929e1a104e3b868d4d7b59ca189a8a431a54e9f3357dfdd81 | Recollidor de credencials / carteres de fase A |
phantom.js (chalk-tempalte:1.0.20) | d1c9e3f296ee9f7d5032f73f9c504cede50334bc14c394055fd5cb9c3a6e08b3 | Col·lector de fase A (variant 1.0.20) |
postinstall.js (chalk-tempalte:1.0.19 = 1.0.20) | ffba9bdd6793edd5b38e12900252c1813a693f59c25af51c3b658cf3f27b6162 | Carregador de fase A, idèntic en bytes en ambdues versions |
Atribució i motivació
Fem un seguiment d'aquesta campanya com a PhantomBot, prenent la marca pròpia de l'operador de la Agent d'usuari: PhantomBot/1.0 capçalera del batec del cor, el/la/els/les servei de bot fantasma unitat de sistema, la com.phantom.bot l'etiqueta LaunchAgent i phantomdeadcode@ identificador de correu electrònic. L'operador és coherent sobre aquest nom en almenys quatre artefactes.
Catàleg de senyals
- Editor - codi mort09284814 a npm. Compte d'un sol ús, correu electrònic d'un sol ús de Tutamail, no SCM verificació. No hi ha cap historial de publicacions prèvies més enllà d'aquesta campanya.
- Reutilització de marca — «phantom» apareix al correu electrònic de l'editor, al nom de fitxer del col·lector de la Fase A (phantom.js), al nom del servei de persistència de la Fase B (servei de bot fantasma), a l'etiqueta LaunchAgent (com.phantom.bot), i a l'agent d'usuari del bot (PhantomBot/1.0).
- Infraestructura — Un únic VPS a 80.200.28.28 fronts Fase A a través de la rotació del subdomini Serveo; Fase B es mou a un localhost.run túnel invers (b94b6bcfa27554.lhr.life). Els serveis dels dos proveïdors són gratuïts i només requereixen SSH de sortida per part de l'operador, cosa que és coherent amb les configuracions de baix pressupost i baixa seguretat operativa.
- estil de codi — JavaScript senzill a tot arreu; sense ofuscació, sense codificació de cadenes, sense comprovacions anti-VM. Els noms de les variables són descriptius (robar informació del sistema, executaCommand, httpFlood). Comentaris a distrube.js adreçar-se directament a un operador futur (“Utilitza la teva URL HTTPS localhost.run”), cosa que suggereix que el fitxer estava pensat per ser redistribuït com un kit, no utilitzat per un sol atacant.
- full de seguretat operativa — El fitxer comprimit de la Fase B inclou tant el client del bot com el servidor C2 del costat de l'operador (c2 ELF + c2.go font). Això és coherent amb un operador que va enviar el seu arbre de treball a npm sense auditar la llista de fitxers. O bé l'operador no té experiència o bé el kit és significar per ser distribuït públicament i el binari C2 forma part del producte.
- Autoconfirmació - axois-utils:1.0.4 conté el comentari font // Canvia a '80.200.28.28' per a públic a la línia 12, confirmant la progressió del desenvolupament / posada en escena / producció que els operadors solen negar.
Motivació
La càrrega útil de la Fase A és un robatori financer directe: les credencials, les claus al núvol, els tokens de GitHub i els moneders criptogràfics tenen mercats de revenda líquids. La Fase B també és financera, però indirecta: els serveis DDoS de lloguer ("booter") lloguen capacitat d'inundació per minut, i els bots com el que s'envia aquí són l'inventari amb què s'executen aquests serveis. El batec del cor de 30 segons, el genèric target/port/durada l'esquema de comandament i l'arsenal d'inundació de cinc protocols són els standard producte d'un operador d'arrencada.
Executar els dos mòduls en paral·lel — chalk-template:1.0.19 i 1.0.20 continuar enviant el lladre mentre axois-utils:1.0.9 envia el bot — suggereix que l'operador està cobrint els fluxos d'ingressos en lloc d'abandonar la Fase A. El pivot és un addició, no un substitut.
El que no reivindiquem
No hem pogut confirmar una identitat real darrere del codi mort09284814 identificador, i no atribuïm aquesta campanya a cap actor, grup o país d'amenaces amb nom propi. La marca "fantasma" és prou coherent en tots els artefactes per suggerir un únic operador, però l'enviament en forma de kit del binari C2 deixa oberta la possibilitat que futurs paquets d'identificadors no relacionats reutilitzin el mateix codi.
Impacte, tendències i què haurien de fer els defensors
impacte
Els objectius legítims d'okupes axis i plantilla de guix són àmpliament depenents en l'ecosistema JavaScript; axis per si sol es troba entre els trenta paquets npm més descarregats. Els noms dels typosquat estan a una tecla de distància dels reals (axois ↔ axis, plantilla ↔ template), i ambdues són faltes d'ortografia lingüísticament plausibles.
No vam poder obtenir estadístiques de descàrrega fiables per a les versions malicioses abans de la retirada: npm no conserva els recomptes de descàrrega per versió després que un paquet no es publiqui, i npms.ioels proxys d'estil són sorollosos a aquesta escala. Qualsevol organització el fitxer de bloqueig de la qual resolgui en un paquet anomenat axois-utils or plantilla de guix de l'editor codi mort09284814 s'ha de tractar com a compromesa: rotar totes les credencials presents a procés.entorn a l'amfitrió afectat, auditeu els vectors de persistència per sistema operatiu (vegeu "Què han de fer els defensors" a continuació) i elimineu la dependència.
Patrons emergents
Aquesta campanya exemplifica un canvi que hem vist en diversos incidents recents de npm: La bastida d'instal·lació amb ganxo és l'actiu durador; la càrrega útil és intercanviableEl mateix editor, el mateix paquet, el mateix preinstal·lació / instal · lar / postinstal·lació triple, i fins i tot la mateixa cadència de bump de versió, l'única cosa que va canviar entre axois-utils:1.0.6 i axois-utils:1.0.9 era l'arxiu hooks executar. Detecció basada en signatures clau per a la càrrega útil de la Fase A (cadenes de ruta de cartera, phantom.jsEl col·leccionista de 7,667 línies de , l'amfitrió Serveo C2) hauria marcat les tres primeres versions i hauria perdut completament la Fase B.
El mateix patró és visible en altres campanyes del 2026 que hem seguit: un únic operador amb una estructura estable, alternant entre el robatori de credencials, clients que fan trampes en exàmens, expulsió de bots de Telegram i ara el reclutament de DDoS. Els defensors que confien en signatures de càrrega útil continuaran perdent la segona ronda de cada campanya.
El corol·lari és que Els TTP en temps d'instal·lació són el millor senyal. Declaracions triples d'instal·lació de ganxo, scripts d'instal·lació que importen https or procés_fill, instal·leu scripts que escriguin a les carpetes d'inici de l'usuari i instal·leu scripts que resolguin noms d'amfitrió en serveis de túnel invers gratuïts (Serveo, localhost.run, ngrok, cloudflared) són rars en paquets legítims i comuns en paquets maliciosos.
Què haurien de fer els defensors
- Auditoria de fitxers de bloqueig. Cerca cada package-lock.json / fil.bloqueig / pnpm-lock.yaml a la vostra organització per a les cadenes exactes axois-utils i plantilla de guixTracta qualsevol partit com un compromís.
- Rotar secrets sobre els hostes afectats. Fase A: Credencials SSH, núvol, GitHub, npm i moneder recollides a granel. Assumeix totes les credencials que hi hagi mai presents. procés.entorn, ~ / .Ssh, ~/.aws, ~/.npmrc, ~/.config, o qualsevol .env* El fitxer de l'amfitrió afectat està exposat.
- Eliminar la persistència (Fase B). A Windows, suprimeix HKCU\Software\Microsoft\Windows\Versió actual\Executar\Actualització del sistema, eliminar %APPDATA%\Microsoft\Windows\Menú Inici\Programes\Inici\actualització del sistema.bati schtasks /delete /tn SystemUpdate /fA Linux, crontab -e i eliminar @reboot node …, systemctl –user disable –now phantom-bot.service després suprimiu ~/.config/systemd/user/phantom-bot.service, fregar .bashrc / .zshrc / /etc/rc.localA macOS, launchctl descarrega ~/Library/LaunchAgents/com.phantom.bot.plist a continuació, esborreu el plist.
- Bloqueja els hosts C2. Afegiu els quatre punts finals C2 de la taula IOC a la vostra llista de bloqueig de sortida. *.serveousercontent.com i *.lhr.life es pot bloquejar a l'engròs si el vostre entorn no té cap ús legítim per als serveis de túnel invers.
- Caça per TTP en temps d'instal·lació, no càrrega útil. Entrades de fitxer de bloqueig d'inventari les quals paquet.json declara preinstal·lació, instal · lari postinstal·lació tots apuntant al mateix script. Verifiqueu l'antiguitat del paquet i l'estat de verificació de l'editor. Aquest patró és rar en paquets legítims i és el senyal més fiable que PhantomBot reutilitza.
- Auditoria per al binari C2. Qualsevol persona que hagi descarregat axois-utils:1.0.9 té el servidor C2 de l'operador (c2 ELF, sha256 165fa92d…) al disc. Escaneja les memòries cau i els magatzems d'artefactes de CI. El binari està inactiu per si mateix, però la seva presència en una estació de treball és una prova inequívoca que el paquet s'ha instal·lat.
Línia de tancament
El mateix operador, el mateix paquet i el mateix hook d'instal·lació poden oferir amenaces completament diferents en 48 hores. Vigileu la bastida, no la càrrega útil.




