TL; DR
Pojedynczy wydawca npm, deadcode09284814, przeprowadził kampanię typosquatową przeciwko legalnym axios oraz chalk-template pakiety od połowy maja 2026 r.
Kampania rozpoczęła się od konwencjonalnego złodzieja danych uwierzytelniających i portfeli, który wykradał dane do Tunel HTTPS Serveo.
On 2026-05-17Z axois-utils:1.0.9operator całkowicie zamienił ładunek: ten sam potrójny szkielet instalacyjny, ten sam wydawca, ta sama nazwa pakietu.
Jednak skrypt instalacyjny jest teraz rekrutem botnetu DDoS międzyplatformowego.
Ładunek mówi do localhost.run tuneluje i akceptuje polecenia „flood”, zmieniając zainfekowane środowiska w część botnetu zdolnego do przeprowadzania ataków DDoS.
Operator nawet wysłał Serwer C2 w wersji binarnej w archiwum tarball, wyraźnie pokazującym eskalację od kradzieży danych uwierzytelniających do aktywnej infrastruktury botnetu.
Dwa pakiety, cztery wersje nadal aktywne w rejestrze i jeden operator uruchamiający oba moduły równolegle.
Stopień zagrożenia: wysoki.
Atak: Jak to działa
Kampania opiera się na celowo nudnym schemacie dostawy: dwie błędne nazwy paczek, jedna litera odbiega od nazw paczek z setkami milionów pobrań tygodniowo (aksjos, szablon kredowy), i potrójna instalacja hooks które gwarantują wykonanie. Ciekawe jest to, co stanowi rusztowanie niesie — oraz fakt, że operator zmienił ładunek nie zmieniając niczego innego.
Wspólny rusztowanie
Każda opublikowana wersja obu pakietów deklaruje ten sam trzycykl życia hooks in pakiet.json:
"scripts": { "preinstall": "node <payload>.js", "install": "node <payload>.js", "postinstall": "node <payload>.js" } Wymienienie ładunku pod wszystkimi trzema hooks to przesada — po instalacji sam by działał domyślnie npm zainstalowaćWybór ma znaczenie: npm install –ignore-scripts pomija skrypty, ale kilka typowych przepływów pracy (przywracanie pamięci podręcznej CI, które ponownie uruchamia cykl życia) hooks selektywnie lub deweloperzy, którzy tylko audytują po instalacji) zrób potrójnie redundantną deklarację, co będzie najbezpieczniejszym rozwiązaniem dla atakującego.
szablon kredowy dodaje drugi mechanizm: deklaruje axois-utils:^1.0.7 jako środowisko wykonawcze zależność. Instalacja typosquatted szablon kredowy W związku z tym wciąga również siostrzanego typosquata i oba ładunki są uruchamiane. Te dwa pakiety stanowią skoordynowaną parę, a nie niezależne listy.
Faza A — złodziej danych uwierzytelniających/portfela (2026-05-15 → obecnie)
Faza A to oryginalny ładunek. Ładowarka to krótki postinstall.js który wskazuje na odwrotny tunel HTTPS 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'; Poddomena Serveo koduje adres IP docelowy (80.200.28.28) bezpośrednio w nazwie hosta — rozpoznawalna konwencja dla tej usługi. Operator zmienia losowy prefiks subdomeny między wersjami, aby ominąć naiwne listy blokowania domen, ale podstawowy adres IP nigdy się nie zmienia.chalk-temalte:1.0.14 używany 8a3e818ea8f11186-80-200-28-28…; 1.0.16 / 1.0.19 / 1.0.20 użycie f04a273bd84c0622-….)
postinstall.js ręce precz phantom.js, moduł „kolekcjonerski” składający się z 7,667 linii. phantom.js spaceruje po gospodarzu:
Prywatne klucze SSH (~/.ssh/*) |
.npmrc zawartość i wszelkie npm_* tokeny środowiskowe |
| Pliki poświadczeń AWS, GCP i Azure |
GitHub personal-access-token regex (ghp_*, gho_*, ghu_*, ghs_*) |
| Artefakty portfeli kryptowalutowych dla Bitcoin, Exodus, Electrum, Monero, Litecoin, Dogecoin, Zcash, Dash |
Rekurencyjny .env* przejść przez ~/projects, ~/dev, ~/code, ~/workspacei instalacja cwd |
Historie muszli i pełna wersja process.env |
Pakiet jest wysyłany pocztą do tunelu Serveo pod adresem / zbieraćNie ma tu żadnego zaciemniania, żadnej logiki anty-VM, żadnego przygotowania — operator stawia na głośność i szybkość.
Faza B — rekrutacja PhantomBot DDoS (2026-05-17, axois-utils: tylko 1.0.9)
Faza B zastępuje pliki phantom.js + postinstall.js pojedynczym plikiem o nazwie distrube.js (literówka pochodzi od operatora). Rusztowanie z potrójnym hakiem w pliku package.json pozostaje niezmienione; pakiet zachowuje tę samą nazwę, zakres i wzorzec zmiany wersji. Z zewnątrz axois-utils:1.0.9 wygląda jak pomniejsza kontynuacja wersji 1.0.6. Wewnątrz to zupełnie inna rodzina złośliwego oprogramowania.
distrube.js otwiera się blokiem konfiguracyjnym, który nadaje nazwę własnej marce operatora:
// 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')}`; |
Komentarze są skierowane do przyszłego operatora, który będzie obsługiwał zestaw („Użyj adresu URL HTTPS localhost.run”). To, a także to, co jest przesyłane do klienta bota, wskazuje, że to nie jest po prostu ładunek ofiary, ale cały zestaw.
Przepływ:
- Uporczywość uruchamia się jako pierwszy. Skrypt instaluje się na trzy różne sposoby w zależności od systemu operacyjnego (rejestr Uruchom + Folder startowy + schtasks w systemie Windows; crontab + usługa phantom-bot jednostka systemd + .bashrc/.zshrc dołącz + /etc/rc.local na Linuksie; LaunchAgent com.phantom.bot.plist (w systemie macOS). Nazwa usługi trwałości i etykieta LaunchAgent są zarówno bot-widmo / com.phantom.bot, skąd też wzięła się nazwa kampanii.
- Wyciek informacji o systemie uruchamia się raz — jednorazowy odcisk palca POST do b94b6bcfa27554.lhr.life:443/collect zawierający nazwę hosta, platformę, architekturę, nazwę użytkownika, procesor/pamięć RAM, interfejsy sieciowe, process.env, cwd, homedir, wersję węzła i publiczny adres IP. To znacznie mniej agresywne rozwiązanie niż faza A: brak SSH, brak portfeli, brak rekurencji .env. Zadaniem bota jest rejestracja, a nie kradzież.
- Pętla bicia serca co 30 sekund otwiera żądanie HTTPS POST do b94b6bcfa27554.lhr.life:443/. User-Agent to PhantomBot/1.0. Weryfikacja TLS jest jawnie wyłączona (rejectUnauthorized: false). Odpowiedź C2 jest analizowana jako JSON w formacie {typ, cel, port, czas trwania, wątki, metoda} i wysyłana.
- Arsenał powodziowy jest powiązany z sześcioma poleceniami:
| Typ polecenia | Moduł | Komentarz |
|---|---|---|
| świst | Odpowiedź na żywość | Bot identyfikuje się |
| http | Powódź HTTP | Powódź żądań warstwy 7 |
| https | Powódź HTTPS | Tak samo jak http, w opakowaniu TLS |
| tcp | Powódź TCP | 65 KB losowego spamu |
| udp | powódź UDP | Pakiety UDP o rozmiarze 65 507 bajtów |
| szybki | HTTP/2 – szybki reset DoS | Technika CVE-2023-44487 z 2023 r. |
Wszystkie pięć modułów przeciwpowodziowych zajmuje cel, Port, czas trwania, threads Argument — bot to generyczny, płatny flooder, nieskierowany do żadnej konkretnej ofiary. Lista ofiar operatora znajduje się w C2, a nie w pakiecie.
Co nowego — dostarczony plik binarny C2
Faza A to znany schemat: kradzież danych uwierzytelniających, instalacja haka, tunelowanie C2 przez dostawcę. Faza B to również Znajomy kształt — botnety DDoS są od lat nieodłącznym elementem złośliwych pakietów npm. Nietypowe jest to, że operator wysłał strona serwera zestawu znajdującego się w archiwum npm:
- c2 — skompilowany plik binarny Go ELF o rozmiarze 4 megabajtów
- c2.go — 426-liniowe źródło Go dla tego kodu binarnego
Żaden z plików nie jest wywoływany przez żaden hak instalacyjny. Nie są one częścią ładunku ofiary. Znajdują się w katalogu pakietów, tak jak plik dokumentacji. Najbardziej prawdopodobna interpretacja jest taka, że operator przesłał swoje drzewo robocze do npm bez porządkowania listy plików – co stanowi prawdziwą pomyłkę w zakresie bezpieczeństwa operacyjnego – a dostarczony zestaw zawiera kompletny, dwustronny zestaw: klienta uruchamianego przez ofiarę i serwer uruchamiany przez operatora.
To właśnie ta część historii uzasadnia określenie „gotowy zestaw do botnetu”. Każdy, kto pobrał axois-utils:1.0.9 przed usunięciem mają nie tylko próbkę ofiary — mają także działający serwer C2.
Punkt obrotu w jednym zdaniu
Ten sam wydawca, te same nazwy pakietów, ta sama potrójna konstrukcja, ta sama „widmowa” marka — ale ładunek zmienił model monetyzacji z dnia na dzień: od „zbieraj sekrety, które mogę odsprzedać” do „wynajmuj pojemność powodziową, którą mogę wydzierżawić”. Procedury TTP w czasie instalacji, które obrońcy powinni obserwować, są niemal identyczne w obu fazach; obrona oparta na sygnaturach, oparta na ciągach ścieżek portfela fazy A lub phantom.jsKolektor 7,667 linii całkowicie ominąłby fazę B.
| Data (UTC) | wydarzenie |
|---|---|
| 2026-05-15 | Pierwsza publikacja: axois-utils:1.0.4 (wersja testowa LAN, platforma deweloperska na 192.168.129.19) |
| 2026-05-15 | axois-utils:1.0.6 opublikowano — faza A C2 zamieniona na 80.200.28.28 przez tunel Serveo; komentarz źródłowy // Change to '80.200.28.28' for public potwierdza zamianę dev→prod |
| 2026-05-16 | chalk-tempalte:1.0.14 oraz 1.0.16 opublikowany — ładowarka łańcuchowa deklarująca axois-utils:^1.0.7 jako zależność środowiska wykonawczego; poddomena Serveo została obrócona |
| 2026-05-16 | Kampania fazy A odkryta podczas rutynowego skanowania npm; zastosowano werdykty potwierdzające złośliwość |
| 2026-05-17 | axois-utils:1.0.9 opublikowano — obrót ładunku: rekrutacja PhantomBot DDoS przez tunel localhost.run; po stronie operatora c2 binarny i c2.go źródło wysłane w archiwum tarball |
| 2026-05-17 | chalk-tempalte:1.0.19 oraz 1.0.20 opublikowano — nadal faza A (złodziej); operator teraz uruchamia oba moduły równolegle |
| 2026-05-17 | Odkrycie fazy B podczas rutynowego skanowania; werdykty zastosowane we wszystkich 2026-05-17 Wersje |
| (trwający) | Raporty o usunięciu są w trakcie rozpatrywania; wszystkie cztery opublikowane pakiety są nadal dostępne w rejestrze w momencie pisania tego tekstu |
Wskaźniki kompromisu
Pakiety
| ekosystem | Pakiet | wersje |
|---|---|---|
| Npm | axois-utils (literatura aksjosa) | 1.0.4, 1.0.6, 1.0.9 |
| Npm | chalk-tempalte (typosquat kredowego szablonu) | 1.0.14, 1.0.16, 1.0.19, 1.0.20 |
Tożsamość autora
| Pole | Wartość: |
|---|---|
| wydawca npm | deadcode09284814 |
| Adres e-mail wydawcy | phantomdeadcode@tutamail.com |
| SCM weryfikacja | Żaden |
Dowodzenie i kontrola
| Faza | Punkt końcowy | Transport |
|---|---|---|
| A | f04a273bd84c0622-80-200-28-28.serveousercontent.com:443/collect | Tunel HTTPS Serveo |
| A | 8a3e818ea8f11186-80-200-28-28.serveousercontent.com:443/collect | Tunel HTTPS Serveo (wcześniejsza wersja) |
| A | 80.200.28.28:443/collect | Podstawowy punkt końcowy VPS |
| B | b94b6bcfa27554.lhr.life:443/ | localhost.run odwrotny tunel HTTPS |
Podsumowania plików (SHA-256)
| filet | SHA-256 | Komentarz |
|---|---|---|
c2 (Przejdź do ELF, 4 MB) | 165fa92d237fd017c227d00da06ab788212a62be94bf61e95df2d22d00377ef2 | Serwer C2 po stronie operatora, dostarczany wewnątrz axois-utils:1.0.9 |
c2.go (426 wierszy) | 7d0ae79fdb1e9968f3323a3712b624643a782ba3efb2cf3a2cb9c4c5513cea30 | Przejdź do źródła pliku binarnego C2 |
distrube.js | 308b15c023088a7188dea4ef609010ac2493eb4c365b103053d7621a9ca5b935 | Klient bota fazy B |
phantom.js (chalk-tempalte:1.0.19) | 9e380ec88d3ccf3929e1a104e3b868d4d7b59ca189a8a431a54e9f3357dfdd81 | Kolekcjoner danych uwierzytelniających/portfela fazy A |
phantom.js (chalk-tempalte:1.0.20) | d1c9e3f296ee9f7d5032f73f9c504cede50334bc14c394055fd5cb9c3a6e08b3 | Kolektor fazy A (wariant 1.0.20) |
postinstall.js (chalk-tempalte:1.0.19 = 1.0.20) | ffba9bdd6793edd5b38e12900252c1813a693f59c25af51c3b658cf3f27b6162 | Ładowarka fazy A, identyczna bajtowo w obu wersjach |
Atrybucja i motywacja
Śledzimy tę kampanię jako PhantomBot, przejmując własną markę operatora User-Agent: PhantomBot/1.0 nagłówek bicia serca, usługa phantom-bot jednostka systemd, com.phantom.bot Etykieta LaunchAgent i phantomdeadcode@ Adres e-mail. Operator jest konsekwentny w odniesieniu do tej nazwy w co najmniej czterech artefaktach.
Katalog sygnałów
- wydawca Do kod martwy09284814 na npm. Konto z jednym uchwytem, jednorazowy adres e-mail Tutamail, brak SCM weryfikacja. Brak wcześniejszych publikacji poza tą kampanią.
- Ponowne wykorzystanie marki — „phantom” pojawia się w e-mailu wydawcy w nazwie pliku kolekcjonera fazy A (phantom.js), w nazwie usługi trwałości fazy B (usługa phantom-bot), w etykiecie LaunchAgent (com.phantom.bot), a w bota User-Agent (PhantomBot/1.0).
- Infrastruktura — Pojedynczy VPS w 80.200.28.28 fronty Faza A poprzez rotację poddomeny Serveo; Faza B przesuwa się do localhost.run tunel odwrotny (b94b6bcfa27554.lhr.życieObie usługi tego dostawcy są bezpłatne i wymagają jedynie połączenia wychodzącego SSH po stronie operatora, co jest zgodne z konfiguracjami o niskim budżecie i niskim poziomie bezpieczeństwa operacyjnego.
- Styl kodu — Czysty JavaScript w całym tekście; bez zaciemniania, bez kodowania ciągów znaków, bez kontroli anty-VM. Nazwy zmiennych są opisowe (stealSystemInfo, wykonaj polecenie, httpFlood). Komentarze w distrube.js bezpośrednio zwraca się do przyszłego operatora („Użyj adresu URL HTTPS localhost.run”), co sugeruje, że plik miał być rozpowszechniany jako zestaw, a nie używany przez pojedynczego atakującego.
- Błąd w zabezpieczeniach operacyjnych — Archiwum tarball fazy B zawiera zarówno klienta bota, jak i serwer C2 po stronie operatora (c2 ELF + c2.go (źródło). Jest to zgodne z operatorem, który przesłał swoje drzewo robocze do npm bez audytu listy plików. Albo operator jest niedoświadczony, albo zestaw jest Oznaczało ma być rozpowszechniany publicznie, a plik binarny C2 jest częścią produktu.
- Samopotwierdzenie Do axois-utils:1.0.4 zawiera komentarz źródłowy // Zmień na „80.200.28.28” dla adresu publicznego w wierszu 12, potwierdzając postęp prac rozwojowych/przygotowawczych/produkcyjnych, który operatorzy zazwyczaj negują.
Motywacja
Ładunek Fazy A to prosta kradzież finansowa: dane uwierzytelniające, klucze w chmurze, tokeny GitHub i portfele kryptowalutowe mają płynne rynki odsprzedaży. Faza B to również kradzież finansowa, ale pośrednia: usługi DDoS na zlecenie („booter”) wynajmują przepustowość na minuty, a boty takie jak ten przedstawiony tutaj stanowią zasoby, na których działają te usługi. 30-sekundowe bicie serca, ogólny cel/Port/czas trwania schemat poleceń i arsenał pięciu protokołów powodziowych to standard produkt operatora bootera.
Uruchamianie obu modułów równolegle — chalk-temalte:1.0.19 oraz 1.0.20 nadal wysyłaj złodzieja, podczas gdy axois-utils:1.0.9 wysyła bota — sugeruje, że operator zabezpiecza strumienie przychodów, zamiast porzucać fazę A. Punktem zwrotnym jest dodatek, nie zamiennik.
Czego nie twierdzimy
Nie udało nam się potwierdzić prawdziwej tożsamości osoby, która się za nią kryje. kod martwy09284814 handle i nie przypisujemy tej kampanii żadnemu konkretnemu podmiotowi, grupie ani państwu, które mogłyby stanowić zagrożenie. „Fantomowa” marka jest na tyle spójna w przypadku artefaktów, że sugeruje jednego operatora, ale sposób dostarczania pliku binarnego C2 w formie zestawu pozostawia otwartą możliwość, że przyszłe pakiety z niepowiązanych uchwytów będą ponownie wykorzystywać ten sam kod.
Wpływ, trendy i co powinni zrobić obrońcy
Wpływ
Uzasadnione cele przysiadów aksjos oraz szablon kredowy są szeroko stosowane w ekosystemie JavaScript; aksjos Sam znajduje się w czołówce trzydziestu najczęściej pobieranych pakietów npm. Nazwy te są o jedno naciśnięcie klawisza od prawdziwych (aksozi ↔ aksjos, szablony ↔ szablon), przy czym oba są błędami ortograficznymi, które są prawdopodobne pod względem językowym.
Nie udało nam się uzyskać wiarygodnych statystyk pobierania złośliwych wersji przed usunięciem — npm nie przechowuje liczby pobrań dla każdej wersji po wycofaniu publikacji pakietu, a npms.ioSerwery proxy w stylu „-” generują zakłócenia w tej skali. Każda organizacja, której plik blokady jest rozwiązywany na pakiet o nazwie axois-utils or szablon kredowy od wydawcy kod martwy09284814 należy traktować jako zagrożone: wymień wszystkie obecne dane uwierzytelniające proces.env na dotkniętym hoście przeprowadź audyt wektorów trwałości dla każdego systemu operacyjnego (zobacz „Co powinni zrobić obrońcy” poniżej) i usuń zależność.
Nowe wzorce
Kampania ta jest przykładem zmiany, którą zaobserwowaliśmy w kilku ostatnich incydentach npm: rusztowanie instalacyjne jest trwałym atutem; ładunek jest wymiennyTen sam wydawca, ten sam pakiet, ten sam preinstalacja / zainstalować / po instalacji potrójne, a nawet ta sama wersja – rytm podbicia – jedyna rzecz, która się zmieniła axois-utils:1.0.6 oraz axois-utils:1.0.9 był ten plik hooks uruchom. Wykrywanie oparte na sygnaturach, oparte na ładunku fazy A (ciągi ścieżek portfela, phantom.jsKolektor 7,667 linii, host Serveo C2, oznaczyłby pierwsze trzy wersje i całkowicie pominąłby fazę B.
Ten sam schemat widoczny jest w innych kampaniach z 2026 roku, które śledziliśmy: jeden operator ze stabilnym systemem, na zmianę kradnący dane uwierzytelniające, oszukujący na egzaminach, wyprowadzający boty Telegramu, a teraz werbujący ofiary ataków DDoS. Obrońcy, którzy polegają na sygnaturach danych, będą przegrywać drugą rundę każdej kampanii.
Wniosek jest taki, że TTP w czasie instalacji to lepszy sygnał. Potrójne deklaracje hooków instalacyjnych, skrypty instalacyjne importujące https or proces_potomny, zainstaluj skrypty, które zapisują w folderach startowych użytkownika i zainstaluj skrypty, które rozwiązują nazwy hostów w bezpłatnych usługach odwrotnego tunelowania (Serveo, localhost.run, ngrok, cloudflared) zdarzają się rzadko w legalnych pakietach, ale często w pakietach złośliwych.
Co powinni zrobić obrońcy
- Audyt pliku blokady. Przeszukaj każdy pakiet-lock.json / yarn.lock / pnpm-lock.yaml w Twojej organizacji, aby uzyskać dokładne ciągi znaków axois-utils oraz szablon kredowy. Traktuj każde spotkanie jako kompromis.
- Obróć sekrety na zainfekowanych hostach. Faza A – zbiorcze dane uwierzytelniające SSH, chmurę, GitHub, npm i portfel. Załóżmy, że wszystkie dane uwierzytelniające są obecne. proces.env, ~ / .ssh, ~/.aws, ~/.npmrc, ~ / .configlub dowolny .env* plik na zainfekowanym hoście zostanie ujawniony.
- Usuń trwałość (faza B). W systemie Windows usuń HKCU\Software\Microsoft\Windows\CurrentVersion\Run\SystemUpdate, usuń %APPDATA%\Microsoft\Windows\Menu Start\Programy\Uruchamianie\system-update.bat, schtasks /delete /tn SystemUpdate /f. W systemie Linux, crontab -e i usuń @reboot węzeł …, systemctl –user disable –now phantom-bot.service następnie usuń ~/.config/systemd/user/phantom-bot.service, szorować .bashrc / .zshrc / /etc/rc.local. Na macOS, launchctl unload ~/Library/LaunchAgents/com.phantom.bot.plist następnie usuń plik plist.
- Zablokuj hosty C2. Dodaj cztery punkty końcowe C2 z tabeli IOC do listy blokowanych wyjść. *.serveousercontent.com oraz *.lhr.life mogą zostać zablokowane hurtowo, jeśli w twoim środowisku nie ma uzasadnionego zastosowania dla usług odwrotnego tunelu.
- Polowanie według czasu instalacji TTP, nie ładunek. Wpisy pliku blokady inwentarza, których pakiet.json deklaruje preinstalacja, zainstalować, po instalacji Wszystkie wskazują na ten sam skrypt. Sprawdź wiek pakietu i status weryfikacji wydawcy. Ten wzorzec jest rzadki w przypadku legalnych pakietów i jest najbardziej wiarygodnym sygnałem, że PhantomBot ponownie wykorzystuje.
- Audyt binarny C2. Każdy, kto pobrał axois-utils:1.0.9 posiada serwer C2 operatora (c2 ELF, sha256 165fa92d…) na dysku. Przeskanuj pamięć podręczną i magazyny artefaktów CI. Plik binarny sam w sobie jest uśpiony, ale jego obecność na stacji roboczej stanowi jednoznaczny dowód na to, że pakiet został zainstalowany.
Linia zamykająca
Ten sam operator, ten sam pakiet i ten sam hak instalacyjny mogą dostarczyć zupełnie innych zagrożeń w ciągu 48 godzin. Uważaj na rusztowanie, a nie na ładunek.




