PhantomSync: npm-kryptopaketit Piilota lompakon varastaja

PhantomSync: kahdeksan kryptokehittäjän npm-pakettia piilottaa viivästyneen, itsestään pysyvän pudottajan

TL; DR

Yksi npm-julkaisija lähetti kahdeksan pientä pakettia, joiden nimet tuntuivat lohkoketju- ja lompakkokehityksen arkipäiväisiltä rakennuspalikoilta. base58-utils, abi-encode, eth-dev, arb-kit, layer2-sdk, solana-key-utils, eth-wallet-helpersja crypto-validate-libJokainen sisältää toimivan apuohjelman. Apuohjelman jälkeen on kuitenkin liitetty itseään kutsuva koodilohko, joka suoritetaan heti, kun moduuli tuodaan.

Noin 37 sekuntia tuonnin jälkeen, joka lohko dekoodaa paketin sisällä testilaitteeksi naamioidun hyötykuorman, kirjoittaa sen käyttäjän kotihakemistoon piilotettuun tiedostoon ja rekisteröi itsensä käynnistymään uudelleen joka login Windowsissa, macOS:ssä ja Linuxissa ja käynnistää dekoodatun komentosarjan erillisenä prosessina. Tässä ei ole mitään tekemistä npm-asennuksen kanssa; se odottaa koodin tuontia ja suorittamista, mikä on asennuksen kaltaista hiljaisempaa aikaa.

Hyötykuorma ei ole läpinäkymätön. Se toimitetaan tavallisena base64-muodossa, joten "testauslaitteen" dekoodaus palauttaa toisen vaiheen kokonaisuudessaan: a kryptolompakko ja salaisuuksien varastaja joka odottaa koneen olevan käyttämättömänä, kerää yksityiset avaimet ja siemenlausekkeet, salaa jokaisen löydön kovakoodatulla RSA-4096-avaimella ja purkaa sen kiinnittämällä sen julkiseen IPFS-tallennustilaan ja lähettää takaisin 12 tunnin välein.

Seuraamme klusteria seuraavasti PhantomSyncKaikki kahdeksan pakettia olivat analyysin tekohetkellä saatavilla npm-rekisterissä yhden tilin alla.

ekosysteemiNPM
Jäsenyydetbase58-utils, abi-encode, eth-dev, arb-kit, layer2-sdk, solana-key-utils, eth-wallet-helpers, crypto-validate-lib
KohdealustojaWindows, macOS, Linux
YdinkäyttäytyminenViivästetty, tuonnin aikana piilotettu pudotin testikiinnittimeksi; asentaa alustojen välisen pysyvyyden
hyötykuormaKryptovaluuttalompakko ja salaisuuksien varastaja, RSA-4096-salaus, vuoto julkisen IPFS-pinauksen kautta

Hyökkäyksen anatomia

Jokainen paketti näyttää ensimmäisellä lukukerralla vaatimattomalta. base58-utilson esimerkiksi muutaman kilotavun mittainen nollariippuvainen Base58 / Bitcoin-WIF-apukoodi – juuri sitä mitä nimi lupaa. Asiaankuuluva koodi sijaitsee jälkeen moduulin moduuli.vienti, johon tiedoston alkuun silmäilevä lukija ei todennäköisesti katso: itseään kutsuva funktio, joka aikatauluttaa itsensä ajastimella.

Paketin lähdekoodista rekonstruoitu operaatioketju toimii näin:

1. Package is required() by the host project 2. A self-invoking function schedules a callback ~37,000 ms later (setTimeout) 3. On fire, the callback reads test/fixtures/keypairs.dat (a base64 blob) 4. It base64-decodes that blob into a Node.js script 5. It writes the script to ~/.cache-db/.node-sync/syncd.js (mode 0o700) 6. It installs login-persistence for that script (see below) 7. It spawns "node syncd.js" as a detached process

Kaksi suunnitteluvaihtoehtoa erottuu joukosta.

Hyötykuorma kulkee testilaitteena. Toista vaihetta ei kirjoiteta itsestään selvänä koodina. Se sijaitsee testi/kalusteet/avainpairs.dat, base64-tiedosto, jonka nimi sulautuu pakettiin, joka väittää käsittelevänsä avainpareja. Tarball-tiedostoa silmäilevälle ihmiselle se näyttää esimerkkidatalta; liitettävälle koodille se on dekoodattava ja suoritettava skripti. Dropper itsessään ei sisällä verkko-osoitetta – ne sijaitsevat toisessa vaiheessa – mutta siinä ei ole ylimääräistä hämärrystä: kiinnityslaite on yksi base64-kerros, joten sen dekoodaus (base64 -d) palauttaa täyden syncd.js ja sen verkkokäyttäytymistä. Seuraavassa osiossa käydään läpi, mitä kyseinen palautettu vaihe tekee.

Räjäytys on viivästynyt ja sidottu tuontiin, ei asennukseen. Koska liipaisin on vaatia () plus noin 37 sekunnin ajastin asennuskoukun sijaan, toiminta ohittaa tarkistukset, jotka tarkkailevat vain npm asentaa vaihe, ja viive kestää pidempään kuin monet lyhytikäiset hiekkalaatikko- ja CI-ajot. Siihen mennessä, kun mikään suoritetaan, paketin vetänyt asennus on jo kauan sitten päättynyt.

Kun dekoodattu skripti on levyllä osoitteessa ~/.cache-db/.node-sync/syncd.js — polku, joka on valittu luettavaksi kuten tavallinen välimuistihakemisto — dropperin avulla se selviää uudelleenkäynnistyksissä kaikilla kolmella pääalustalla:

  • Linux: cron-merkintä, joka käynnistää komentosarjan uudelleen. Merkintä asennetaan suodattamalla olemassa oleva crontab läpi grep -v syncd, jolla on sivuvaikutuksena se, että uusi merkintä jää pois tavallisesta listauksesta, joka suorittaa grep-haun saman nimen osalta.
  • Windows: ajoitettu tehtävä nimeltä WinNodeSync, asetettu toistumaan 12 minuutin välein.
  • MacOS: käynnistetty työ, jonka nimi on com.apple.syncd, joka esiintyy useissa paketeissa – merkintä, joka jäljittelee laillista Applen järjestelmäpalvelua.

Skripti käynnistetään sitten välittömästi irrotettuna prosessina, joten se jatkaa suoritusta tuontiohjelman sulkeuduttua.

Mitä toinen vaihe tekee

Koska kiinnityslaite on yksi base64-kerros, toinen vaihe dekoodaa puhtaasti ja se voidaan lukea kokonaan. Kaikissa kahdeksassa paketissa on yksi saman skriptin kolmesta muunnelmasta, joka identifioituu otsikkokommentissa seuraavasti: phantom syncd v3 — topo durmiente (”nukkuva myyrä”). Sen tehtävänä on varastaa kryptovaluuttalompakoiden materiaalia ja kehittäjien salaisuuksia ja lähettää ne pois koneelta. Se toimii seuraavasti:

  • 1. Odota, kunnes kone on käyttämätön. Ennen kuin teet mitään, syncd.js tarkistaa, kuinka kauan käyttäjä on ollut passiivinen, ja jatkaa vain tietyn kynnyksen (noin 15 minuuttia) ylittämisen jälkeen — xprintidle Linuxissa ioreg HIDIdleTime macOS:ssä ja PowerShell-kysely tyhjäkäyntiaikana Windowsissa. Tietojen kerääminen tapahtuu siis yleensä silloin, kun kukaan ei ole näppäimistöllä.
  • 2. Hae etäohjattava aktivointikytkinSkripti noutaa pienen konfiguraation tyhjästä hakemistosta ennen toimintaa. Ensisijainen lähde on GitHubin gist-raaka-URL (gist.githubusercontent.com/juang55/…/cfg.txt); skripti aktivoituu vain, jos kyseinen konfiguraatio lukee aktiivinen=1Jos ydinsisältöä ei ole saatavilla, käytetään kolmea kovakoodattua IPFS-sisältötunnistetta, jotka noudetaan julkisten yhdyskäytävien kautta. gateway.pinata.cloud, ipfs.ioja cloudflare-ipfs.comTämä antaa käyttäjälle jälkikäteen tapahtuvan virittämisen/riisunnan hallinnan ja alasviennin kestävän varamekanismin. (Pienin versio, toimitetaan krypto-validate-lib, eth-lompakko-apulaisetja solana-key-utils, josta on poistettu gist-kerros ja joka perustuu pelkästään IPFS-tunnisteisiin.)
  • 3. Kerää lompakkomateriaalia ja salaisuuksia. Skripti kulkee käyttäjän kotihakemistossa — ~/.config/solana, ~/.ethereum/keystore, ~/.foundry, ~/.hardhat, ~ / .sshja pöytä-/asiakirjat/Lataukset (mukaan lukien espanjankieliset kansioiden nimet) sekä ~/.env ja shell rc -tiedostot ja vastaavat AppData sijainteja Windowsissa. Se kohdistuu Ethereumin yksityisiin avaimiin, Bitcoinin WIF-avaimiin, BIP-39-siemenlausekkeisiin, Solanan avainpareihin, Ethereumin avainsäilön JSON-muotoon, SSH-avaimiin ja salaisuuksia sisältäviin ympäristömuuttujiin. Suurempi variantti (sisältää abi-koodaus, base58-utils, eth-dev) sisältää täyden 2048 sanan BIP-39-sanakirjan ja käyttää säännöllisiä lausekkeita uute yksittäisiä avaimia ja validoituja siemenlausekkeita mistä tahansa lukemastaan ​​tekstistä; kaksi pienempää muunnosta yhdistävät tiedostot avainsanan mukaan (siemenet, muistintuki, lompakko, metamask, aave, pääkirja, laatikko, …) ja lataa kokonaisia ​​tiedostoja.
  • 4. Salaa ja pura tiedot julkisen pinauspalvelun kautta. Jokainen löydös on yhdistetty isännän sormenjälkeen (käyttäjätunnus@isäntänimi, alusta, aikaleima) ja salattu skriptiin upotetulla kovakoodatulla RSA-4096-julkisella avaimella. Salattu tietue ladataan sitten kiinnittämällä se IPFS:ään kautta api.pinata.cloud/pinning/pinJSONToIPFS, todennettu kovakoodatuilla Pinata API -tunnistetiedoilla. Ei ole olemassa räätälöityä C2-palvelinta, jota takavarikoida: varastettu data on tallennettu julkiseen hajautettuun tallennustilaan, josta operaattori voi noutaa sen tuloksena olevien sisältöhajautusten avulla. Latausten välissä on muutaman sekunnin satunnainen jitter ja paikallinen loki aikaleima | avaintyyppi | palautettu hash-arvo pidetään osoitteessa ~/.cache-db/.node-sync/.sl.
  • 5. Jatka ja anna signaalin 12 tunnin syklissä. Toinen vaihe palauttaa oman pysyvyytensä — cron-merkintä Linuxissa, a com.apple.syncd launchd-työ macOS:ssä ja ajoitettu tehtävä nimeltä WindowsNodeSync Windowsissa – asetettu suoritettavaksi uudelleen 12 tunnin välein. Huomaa, että tämä on eri Windows-tehtävän nimi siitä, jonka dropper asentaa (WinNodeSync); molemmat ovat metsästyksen arvoisia.

Aikajana

Kahdeksan pakettia julkaistiin tiukassa sarjassa 13.7.2026 ja 14.7.2026. Useissa on useampi kuin yksi versio; pipetti on identtinen eri versioissa, ja vain rivien siirtymät muuttuvat sen yläpuolella olevan hyvänlaatuisen hyödyllisyyskoodin koon muuttuessa.

Päivämäärä Tapahtuma
2026-07-13 Klusterin ensimmäiset paketit näkyvät yhden julkaisijan alla (solana-key-utils, eth-wallet-helpers, crypto-validate-lib ja muiden varhaiset versiot)
2026-07-13 → 07-14 Jäljellä olevat nimet ja jatkoversiot julkaistu; samat liitetyt tiputusalukset jokaisessa
2026-07-14 Kaikki kahdeksan merkitty ja analysoitu; jokainen paketti edelleen asennettavissa rekisteristä

Purkauksen aikana julkaisijan rekisterin maine muuttui klusterin alun suunnilleen neutraalista vahvasti negatiiviseksi havaittujen pakettien kertyessä – tämä on havaittavissa oleva sivuvaikutus pakettien merkitsemisestä, ei suunniteltu ominaisuus.

Kompromissin indikaattorit

Kaikkien alla olevien indikaattoreiden – ”toisen vaiheen” taulukoissa olevien dekoodaamalla saatujen – esiintyminen varmistui analyysihetkellä. testi/kalusteet/avainpairs.dat ja lukemalla toipunutta syncd.js.

Tiedostot ja polut

Osoitin Rooli
~/.cache-db/.node-sync/syncd.js Dekoodattu toinen vaihe, kirjoitettu moodilla 0o700
~/.cache-db/.node-sync/.sl Paikallinen tiedonkeruuloki (aikaleima | avaintyyppi | IPFS-hajautus)
test/fixtures/keypairs.dat Base64-koodattu hyötykuorma, joka on asetettu tarballin sisään "testauslaitteistoksi"

Toisen vaiheen verkkoinfrastruktuuri (palautettu syncd.js-tiedostosta)

Osoitin Rooli
gist.githubusercontent.com/juang55/b298754cb72942b1cdcf02ccd45cde2f/raw/cfg.txt Aktivoinnin esto; skripti suoritetaan vain, jos konfiguraatio lukee active=1
Qmcqz3w8j4qFQXDAXAxnrdc2oSX3nzBT4NqtpTqL8mr1ga IPFS-konfiguraation varajärjestelmä (CID)
QmdTXoqVmTHY1i4ZWLdLkoQ9YChp5TXPh5cWXwnAYZt5iF IPFS-konfiguraation varajärjestelmä (CID)
QmfJkLU5gdCpqbbqEjWYC2anXW9FmuEeSLLeLiHVJKYUjp IPFS-konfiguraation varajärjestelmä (CID)
gateway.pinata.cloud, ipfs.io, cloudflare-ipfs.com IPFS-yhdyskäytävät, joita käytetään määritysten noutamiseen varajärjestelmänä
api.pinata.cloud/pinning/pinJSONToIPFS Pakkolunastuksen päätepiste, varastettu data kiinnitetty julkiseen IPFS:ään
Pinata API -avain 13c766575b9270a9825d, kovakoodatut ulosvirtaustunnistetiedot

Toisen vaiheen keräyskohteet (palautettu syncd.js-tiedostosta)

Osoitin Rooli
~/.config/solana, ~/.ethereum/keystore, ~/.foundry, ~/.hardhat, ~/.ssh, ~/.env, shell rc -tiedostot Avainten ja salaisuuksien etsintä hakemistoissa/tiedostoissa
AppData\Roaming\Solana, AppData\Local\ethereum\keystore Windows-vastineet haettuina
Kerätyt artefaktityypit ETH-yksityiset avaimet, Bitcoin WIF, BIP-39-siemenlausekkeet, Solana-avainparit, Ethereumin avainsäilö JSON, SSH-avaimet, salaiset ympäristömuuttujat

Pysyvyysartefaktit

foorumi Osoitin
Linux cron-merkinnän käynnistys syncd.js; asennettu crontabin kautta suodatettuna grep -v syncd
Windows ajoitettu tehtävä WinNodeSync (pipetti) ja WindowsNodeSync (toinen vaihe)
macOS launched-tarra com.apple.syncd
Kaikki Toinen vaihe toistuu 12 tunnin sykleissä

Behavioral

  • Itseään kutsuva funktio liitetään perään moduuli.vienti, ajoitus a setTimeout noin 37 000 ms tuonnin yhteydessä.
  • lapsiprosessi spawn("solmu", ) irrotetun lisäasetusjoukon kanssa.
  • Tyhjäkäyntiohjattu aktivointi toisessa vaiheessa (xprintidle / ioreg HIDIdleTime / PowerShell-lepoaika; ~15 minuutin kynnysarvo).
  • RSA-4096-salaus per-finding, sitten HTTPS POST julkiseen IPFS-pinning-APIin.

Paketit ja versiot (npm, julkaisija solbuilder_io)

Paketti versiot
base58-utils 1.0.0, 1.0.1, 1.0.3
abi-encode 1.0.0, 1.0.1, 1.0.2
eth-dev 1.0.0, 1.0.1, 1.0.2
arb-kit 1.0.0, 1.0.1
layer2-sdk 1.0.0, 1.0.1
solana-key-utils 1.0.0
eth-wallet-helpers 1.0.0
crypto-validate-lib 1.0.0

julkaisija

  • solbuilder_io - angel_lopez89[@]proton[.]me, sähköpostiosoite vahvistamaton, ei vahvistettua versionhallintatiliä, ei linkitettyä tietovarastoa.

Attribuutio ja havaittu käyttäytyminen

Kahdeksalla paketilla on yhteinen yksi julkaisijan tili ja yksi hyötykuorma. Jokainen on triviaali paketti – muutaman kilotavun kokoinen oikeaa apuohjelmakoodia, johon on liitetty sama dropper – julkaistu ilman linkitettyä repositoriota ja vahvistamattoman kertakäyttöisen sähköpostiosoitteen alla. Tuo yhdenmukaisuus, jaettu drop-polku, jaetut pysyvyystunnisteet ja jaettu... avainpairs.dat valmistelutiedostot sitovat klusterin yhteen.

Paketit ovat epätavallisen rehellisiä omasta käytöksestään. solana-key-utils sisältää rivikommentteja, jotka kuvaavat liitettävää lohkoa selkokielellä — yksi niistä nimeää sen PHANTOM: näkymätön pysyvyys, toinen (espanjaksi) kuuluu Poista yläosa taustasta, ”aja myyrä taustalla.” Nämä ovat koodin omia merkintöjä siitä, mitä se tekee; tämän viestin kampanjan nimi on johdettu ensimmäisestä tunnisteesta yhdessä väärennetyn solmun ”sync daemon” kanssa (synkronoitu) jota pysyvyyskoneisto jäljittelee.

Kuvaamme vain sitä, mitä koodi havaittavasti tekee. Pakettien nimeäminen – kaikki krypto-, lompakko- ja lohkoketjutyökalutermit – osoittaa kehittäjäyleisön, joka todennäköisimmin hakee ne nimeltä; se ei itsessään määritä kuka julkaisija on. Toinen vaihe oli täysin palautettavissa dekoodaamalla base64-kiinnitys, ja sen toiminta on kuvattu edellä: se kerää lompakkoavaimia, siemenlausekkeita ja salaisuuksia ja suodattaa ne RSA-salattuina julkiseen IPFS-tallennustilaan Pinatan kautta. Merkittävä suunnitteluvalinta on yksityisen C2-palvelimen puuttuminen – kokoonpano saapuu GitHub-gistiltä ja IPFS:ltä, ja varastetut tiedot säilytetään julkisessa hajautetussa tallennustilassa, joka on avattu sisällön hajautuksella, joita molempia on vaikeampi takavarikoida kuin yhtä hyökkääjän hallitsemaa isäntää. Kirjoitushetkellä ei löytynyt aiempaa julkista raporttia, joka vastaisi tätä klusteria.

Kuka on alttiina. Jokainen, joka on lisännyt jonkin näistä paketeista Node-projektiin ja sitten suorittanut koodia, joka tuo sen. Koska detonaatio tapahtuu tuonnin eikä asennuksen aikana, pelkkä paketin läsnäolo ei riitä – vaan mikä tahansa normaali käyttö, joka lataa moduulin, saavuttaa hyötykuorman. Houkuttavat nimet kohdistuvat kehittäjiin, jotka rakentavat Ethereumin, Solanan, Arbitrumin, Layer-2:n ja yleisten lompakko-/koodaustyökalujen varaan – väestöön, jolla todennäköisimmin on juuri ne resurssit, joita toinen vaihe metsästää. Jokainen, joka on suorittanut jonkin näistä moduuleista koneella, joka sisältää lompakkoavaimia, siemenlausekkeita, avainsäilöjä, SSH-avaimia tai... .env salaisuuksien tulisi käsitellä näitä tunnistetietoja vaarantuneina ja kierrättää niitä.

Kaksi sisäistämisen arvoista kaavaa. Ensimmäinen, hyötykuorma kiinnikkeenä: toisen vaiheen toimittaminen base64-muodossa uskottavasti nimetyssä datatiedostossa (testi/kalusteet/avainpairs.dat) pitää paketin näkyvän lähteen siistinä ja siirtää haitallisen sisällön tiedostoon, jota tarkistustyökalut ja ihmisten tekemät silmäykset usein käsittelevät inerttinä datana. Toiseksi, tuontiaikana viivästynyt suoritus ja eri alustojen välinen pysyvyysLiipaisimen siirtäminen pois asennusvaiheesta, ajastimen lisääminen ja sitten sen säilyttäminen cronissa, ajoitetuissa tehtävissä ja launchd:ssä on tarkoituksellinen askel poispäin meluisammista asennusskriptitekniikoista, joita automaattinen rekisterin tarkistus seuraa eniten.

Ohjeita puolustajille ja ylläpitäjille:

  • Käsittele liitetyt koodit jälkeen moduuli.vienti tarkistusprioriteettina — dropper-logiikka piiloutuu usein "todellisen" moduulipinnan alle.
  • Älä oleta datatiedostojen olevan inerttejä. Base64-blob alla testi/otteluohjelma/ joka luetaan ajonaikana ja dekoodataan, on suoritettavan tiedoston vieressä; merkitsee ajonaikaisia ​​lukuja kiinnitystiedostoista, jotka syöttävät Toiminto/eval/write-then-kutea ketju.
  • Metsästä pudotusreittiä ~/.cache-db/.node-sync/ ja pysyvyysyksiköille WinNodeSync (ajoitettu tehtävä) ja com.apple.syncd (launchd) kehittäjäkoneilla, jotka hakivat nämä nimet.
  • Hälytys solmuprosesseista, jotka luovat cron-merkintöjä, ajoitettuja tehtäviä tai launchd-töitä — lailliset kirjastot tekevät tätä harvoin tuonnin yhteydessä.
  • Suosi lukitustiedostoja ja kiinnitettyjä versioita ja tarkista mahdollisten uusien pienten "apuohjelmariippuvuuksien" erot, erityisesti nollariippuvaisia ​​paketteja julkaistu vahvistamattomien tilien toimesta, joihin ei ole linkitettyä arkistoa.

Rekisterinpitäjien kannalta tärkeintä on, että asennusvaiheen valvonta on välttämätöntä, mutta ei riittävää: datatiedoston sisällä oleva tuonnin aikana tapahtuva, ajastimella viivästetty dropper läpäisee vain asennuksen aikana tapahtuvan tarkistuksen, ja pysyvyysvaihe on usein voimakkain jäljellä oleva havaittava signaali.

sca-työkalut-ohjelmisto-koostumusanalyysityökalut
Priorisoi, korjaa ja suojaa ohjelmistoriskisi
Hanki ilmainen tili.
Luottokorttia ei vaadita.

Turvaa ohjelmistokehityksesi ja -toimituksesi

Xygeni-tuotepaketin kanssa