Ektoplasma npm Installation Hooks Der stjæler AWS-legitimationsoplysninger

Ektoplasma: npm installation hooks der indsamler AWS-legitimationsoplysninger bag en container-only-trigger

TL; DR

En klynge af fem npm-pakker, udgivet på tværs af to kontohåndtag, sendt en postinstall hook, der læser cloud-legitimationsoplysninger fra værten og sender dem direkte fra pakken. Pakkerne bærer ghost-and-pirat-navne — coral-wraith, ecto-corsair-whisper-6f3b9, ecto-corsair-flag-x9m4, ecto-rust-read-f3a9c1, ecto-nightly-spirit — og serialisere hvad end de indsamler til en forfalskning ecto_module: YAML-manifestet før det sendes. Vi sporer klyngen som ectoplasma.

Nyttelasten kører kun, når den registrerer et specifikt miljø: en vært, hvis navn er en 12-tegns hex-streng og en arbejdsmappe under /app/node_modules — formen af ​​en containeriseret bygning eller CI-arbejder. Når den gate passerer, forespørger hook'en AWS-instansmetadatatjeneste (IMDSv2) for IAM-rolleoplysninger, opregner AWS Secrets Manager på tværs af tre regioner, dumper miljøvariabler, læser filer under /app, og skraber efter strenge til at erobre flaget. Den filtrerer derefter resultatet ud på to måder: et fyrtårn til en webhook.site indsamler og en manifest-PUT til et rå-IP-slutpunkt med en liste over localhost-first fallbacks.

De senere pakkebeskrivelser lyder "CTF-nyttelast til verdaccio-forsyningskædetestning." Vi rapporterer denne selvbeskrivelse som en observerbar kendsgerning. Selve adfærden - live udgang til en offentlig IP, reelle IMDS-legitimationslæsninger, reelle Secrets Manager-kald - er, hvad den er, uanset betegnelsen, og er grunden til, at disse versioner blev klassificeret som skadelige.

Et navn i klyngen, coral-wraith, stoppede ikke ved en enkelt udgivelse. Den blev genudgivet i hurtig rækkefølge gennem snesevis af versioner på få timer — 1.0.0 klatring til 6.0.0 — og en tidligere udgave af samme navn havde brugt oppustede 9999.0.x versionsnumre, den klassiske form af en forsøg på afhængighedsforvirringPå tværs af den omvæltning modnedes nyttelasten synligt: ​​fra en one-shot host-enumeration beacon til en komplet AWS-legitimations pivot pakket ind i miljøtjek, der holder den stille uden for dens tilsigtede mål.

Pakker 5 navne; coral-wraith alene genudgivet i snesevis af versioner
Ecosystem NPM
Installer vektor postinstall livscyklusscript
Primært mål AWS IAM-rolleoplysninger + hemmelige værdier for Secrets Manager, miljøvariabler /app filer
Exfil webhook.site beacon + rå-IP C2 PUT
Triggerport 12-hex værtsnavn + /app/node_modules cwd, plus en miljøkontrol, der undertrykker nyttelasten uden for den kontekst
Severity høj — cloud-legitimationsoplysninger og administreret hemmelig afsløring fra containeriserede bygge- og runtime-miljøer

Angrebsanatomi

Hver pakke i klyngen er bygget på samme måde: en næsten tom index.js (modul.eksport = {}), en linje pakke.json manuskript — "postinstall": "node postinstall.js" — og nyttelasten i postinstall.jsDet er nok at installere pakken for at køre hook'en; import eller kald er ikke påkrævet.

Målretningsporten. Før den gør noget, kontrollerer ecto-familiens nyttelast sine omgivelser:

function isAppWorker():   host = os.hostname()   if host does NOT match /^[0-9a-f]{12}$/  -> exit   if cwd does NOT contain "/app/node_modules" -> exit   if cwd contains "/tmp/npm-safe"            -> exit   otherwise -> proceed

Et 12-hex værtsnavn er den standardform, Docker tildeler en container, og /app/node_modules er en konventionel installationssti i en container. Den tredje sætning udgår, hvis stien ligner en sandbox-udvindingsmappe. Nettoeffekten er, at nyttelasten forbliver inaktiv på en udviklerbærbar computer eller en analysesandkasse og kun aktiveres i et containeriseret build eller runtime-worker - den type miljø, der mest sandsynligt indeholder live cloud-legitimationsoplysninger. Den tidligste pakke i klyngen, koralånd, har ingen sådan port og kører sin (enklere) samling ubetinget.

KollektionNår porten passerer, skal krogen ud igennem execFileSync("/bin/sh", ["-c", …]) og kører en enkelt sammensat kommando, der i rækkefølge:

1. PUT /latest/api/token to 169.254.169.254          (IMDSv2 token request) 2. GET .../iam/security-credentials/                  (IAM role name) 3. GET .../iam/security-credentials/<role>            (temporary credentials) 4. dump env | sort                                    (environment variables) 5. list /app (excl. node_modules) + cat first 15      (application files) 6. aws secretsmanager list-secrets                    (us-east-1, eu-west-1, eu-central-1) 7. scrape readable files for HTB{...}                 (capture-the-flag strings)

Trin 1-3 er en lærebogsbaseret IMDSv2-hentning: anmod om et sessionstoken, og vedhæft det derefter som X-aws-ec2-metadata-token header til at hente instansens IAM-rolle og den pågældende rolles midlertidige adgangsnøgler. Valget om at implementere IMDSv2 i stedet for den enklere, ikke-godkendte IMDSv1 GET er værd at bemærke — det betyder, at nyttelasten fungerer selv på instanser, der er konfigureret til at kræve tokenbaseret metadataadgang, hvilket er den AWS-anbefalede hærdning. De legitimationsoplysninger, der returneres af trin 3, er kortvarige. AccessKeyId/Hemmelig adgangsnøgle/Polet tripler begrænset til instansens rolle; hvad end den rolle kan gøre, kan indehaveren af ​​disse nøgler gøre i legitimationsoplysningernes levetid.

Trin 4-6 udvider perspektivet. env dump indsamler alt, hvad build- eller runtime-processen har arvet — i praksis er det her, registreringsdatabasetokens, databaseforbindelsesstrenge og API-nøgler oftest findes. / app file walk læser op til femten programfiler udenfor node_modules, som kan overfladekonfiguration, .env filer eller kilde. Trin 6 kalder aws secretsmanager liste-hemmeligheder i tre regioner; de legitimationsoplysninger, der hentes i trin 1-3, er præcis det, der autentificerer disse kald, så IMDS-læsningen og Secrets Manager-optællingen kædes sammen i en enkelt eskalering: instansrolle → administreret hemmelig inventar. Trin 7 er en henvisning til capture-the-flag-framingen - når en HTB{…} Når flaget findes, sendes det separat. Ellers deles den rå, indsamlede klat i fire stykker og sendes.

Senere versioner i klyngen tager eskaleringen videre. I stedet for at stoppe ved en inventarfortegnelse, analyserer de IMDS-svaret og eksporterer de midlertidige nøgler som AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN miljøvariabler, bekræft identiteten med aws sts get-caller-identity, og derefter gennemløbe hver hemmelighed returneret af liste-hemmeligheder ringer aws secretsmanager get-secret-value på hver — hentning af det hemmelige indhold, ikke kun deres navne. De samme versioner læser også processubstituerede flagbinære filer (/læseflag og venner) og forsøge en fragtkørsel mod ethvert Rust-projekt fundet under / app, hvilket udvider høsten ud over cloud-legitimationsoplysninger til det, byggemiljøet eksponerer.

Disse senere versioner bruger også mere aggressive gateways. Ud over 12-hex-hostname og /app/node_modules kontrollerer, inspicerer nyttelasten den aktive pakkeregisterkonfiguration og arbejdsmappestien og afslutter lydløst, når de angiver en analyse- eller spejlkontekst i stedet for et aktivt mål. Den kombinerede effekt er en nyttelast, der ikke gør noget observerbart i de fleste inspektionsmiljøer og kun kører sin fulde samling, hvor den vurderer sig selv til at være på en ægte containeriseret vært.

EksfiltreringDe indsamlede data forlader værten på to kanaler. Først en beacon POST til en fast webhook.site indsamler, der indeholder værtsnavn, numerisk UID, arbejdsmappe og op til 120 KB indsamlede data. For det andet foldes dataene ind i et falsk YAML "modulmanifest" og PUT til /api/moduler/ på en målserver:

ecto_module:   name: "<flag-or-chunk-0>"   version: "1.0.0"   power_level: "<chunk-1>"   ship_deck: "<chunk-2>"   cargo_hold: "<chunk-3>"

Navnene på manifestfelterne (effektniveau, skibsdæk, lastrum) er dekoration — de stjålne data sidder inde i strengværdierne, hvilket er grunden til, at en netværksovervågning ser, hvad der ligner en godartet upload af pakkeregistreringsmanifestet snarere end en åbenlys datadump. Beacon-kanalen bærer mere: POST krop til webhook.site inkluderer værtsnavn, numerisk UID, arbejdsmappe og op til 120 KB af den indsamlede blob, så selv en enkelt vellykket beacon leverer den fulde optagelse. webhook.site er en gratis anmodningsinspektionstjeneste; at bruge den som en indsamler betyder, at operatøren aldrig behøver at oprette sin egen modtageinfrastruktur for den pågældende kanal, og de registrerede anmodninger forbliver i tjenestens bin.

Manifestet PUT følger en reserveliste, der starter med flere 127.0.0.1/localhost porte og går derefter videre til tre offentlige adresser i `154.57.164.0/24` interval, stopper ved det første slutpunkt, der svarer med statusen 2xx. Rækkefølgen "localhost-first" er i overensstemmelse med selvbeskrivelsen "verdaccio testing" (et lokalt register på loopback), men public-IP fallbacks betyder, at dataene forlader værten, når loopback ikke lytter - hvilket vil sige på enhver maskine, der ikke er forfatterens egen testrigg.

Tidslinje

Klyngen viser trinvis kapacitetsvækst snarere end et enkelt fald. Vi sorterer den efter observeret adfærd, ikke efter publiceret vægur:

Stage Pakker / Versioner Adfærd
Tidlig løbetur coral-wraith 9999.0.x Oppustede versionsnumre i overensstemmelse med et forsøg på afhængighedsforvirring; optælling ved installationstidspunkt og exfil
Seed coral-wraith 1.0.0 postinstall indsamler id/env/flag-filer; enkelt PUT til 154[.]57[.]164[.]71:30782, markør ECT-472839
Hurtig iteration coral-wraith 1.0.1 → 6.0.0 Snesevis af udløsninger på timer; nyttelasten øges isAppWorker() gate, IMDSv2-legitimationsudtrækning, den fulde get-secret-value pivot, kontrol af registreringsdatabasen/stimiljøet og markører for dobbelt sink
Parallelle navne ecto-corsair-whisper-6f3b9 1.0.14–1.0.18 Samme gated nyttelast; webhook.site beacon og multi-endpoint fallback-liste
Varianter ecto-rust-read-f3a9c1 1.0.1–1.0.2 Tilføjer ekstra vaskemarkører ECT-987654, ECT-654321, ECT-839201
Varianter ecto-corsair-flag-x9m4 1.0.0, ecto-nightly-spirit 1.1.0 Samme gated nyttelast, samme C2 og beacon

Det definerende træk ved klyngen er dens udgivelsestakt: i stedet for én pakke og én version genudgives det samme navn igen og igen i hurtig rækkefølge, hver udgivelse en lille variation af den sidste, sammen med en håndfuld forskelligt navngivne søskende, der bærer den samme nyttelast. Inden for hviske familie opdelte koden sig i to tætte fingeraftryk — et sæt, der udløser to kritiske detektioner, et andet tre (en ekstra fillæsningssink) — men begge løser op til den samme nyttelast; forskellen er kodedrift, ikke en adfærdsmæssig forgrening. Versioner af hviske uden for det analyserede interval (op til mindst 1.0.25 på tidspunktet for skrivningen) blev observeret live i registret, og koralånd navnet fortsatte med at klatre op på sin egen versionsstige over det samme vindue.

Indikatorer for kompromis

Alle indikatorer nedenfor blev udtrukket fra pakkekilden på disken. Netværksindikatorer er defangede.

Netværk

Indikator roller
hxxp://154[.]57[.]164[.]71:30782 C2 PUT-mål (coral-wraith)
hxxp://154[.]57[.]164[.]80:30543 C2 PUT-fallback (ecto-*)
hxxp://154[.]57[.]164[.]82:31250 C2 PUT-fallback (ecto-*)
hxxp://154[.]57[.]164[.]71:31289 C2 PUT-fallback (ecto-*)
hxxps://webhook[.]site/602a4c72-7033-4e28-92ea-dc66e59206e5 Beacon-samler
169[.]254[.]169[.]254/latest/... Læsning af IMDSv2-legitimationsoplysninger (målside, AWS-metadata)

Adfærdsmæssig/fil

Indikator roller
"postinstall": "node postinstall.js" Installer vektor
ecto_module: YAML med power_level / ship_deck / cargo_hold nøgler Exfil manifestskema
Vaskmarkører ECT-472839, ECT-987654, ECT-654321, ECT-839201 C2-stisegment /api/modules/<marker>
isAppWorker() port: vært /^[0-9a-f]{12}$/, cwd indeholder /app/node_modules Aktiveringsbetingelse
aws secretsmanager list-secrets i løbet af us-east-1, eu-west-1, eu-central-1 Optælling af hemmeligheder
HTB{...} regex-skrabning Capture-the-flag-høst

Filhashes (sha256, registreret på analysetidspunktet)

File (Felt) sha256
coral-wraith/postinstall.js ce5ff035cfdfed1d0015446424b352c27b66bcb77e9fdb0a51e4245199146824
ecto-corsair-whisper-6f3b9 1.0.18/postinstall.js b58432acba376aa6976f0490d9a1c04257ccdbc856d8390260c50322d63e31c3

Attribuering og observeret adfærd

De fem pakkenavne blev udgivet under to npm-kontonavne, men de deler nok infrastruktur til at behandle dem som én klynge: den samme ecto_module manifest skema, det samme ECT-472839 primær vaskmarkør, den samme webhook.site indsamler-ID og C2-slutpunkter i det samme 154.57.164.0/24` blok. Frøpakken (`coral-wraith, enklere og ikke-gatede) og den gatede ekto-familie læses således som iterationer på ét værktøjssæt snarere end uafhængige indsatser.

Pakkerne beskriver sig selv, i senere versioner, som "CTF-nyttelast til Verdaccio-forsyningskædetestning." Vi fremhæver denne betegnelse som en observerbar kendsgerning og gentager den ikke som en konstatering af formål. Det, koden gør, er utvetydig og uafhængig af, hvordan den er mærket: den læser IAM-rollelegitimationsoplysninger fra instansens metadatatjeneste, opregner administrerede hemmeligheder på tværs af tre AWS-regioner og sender resultaterne til en offentlig IP og en tredjeparts webhook-indsamler. En ægte loopback-only testharness ville ikke have brug for public-IP fallback-listen, IMDS-legitimationslæsningerne eller cross-region Secrets Manager-kaldene. Fordi udgående og legitimationsoplysningernes rækkevidde er reelle, blev de gatede versioner klassificeret som skadelige.

Container-only-gaten er den mest operationelt bemærkelsesværdige egenskab. Det er både en undvigelsesforanstaltning – at forblive tavs på bærbare computere og i analysesandkasser – og en målrettet foranstaltning, der kun aktiveres, hvor en reel IAM-rolle og live hemmeligheder er mest sandsynlige. Analytikere, der kører disse pakker i en generisk sandkasse, ville ikke observere noget; adfærden manifesterer sig kun under et Docker-lignende værtsnavn og en installationssti i containeren.

Eksponeringen her er cloud-legitimationsoplysninger og afsløring af hemmeligheder i build- og runtime-containere. En IAM-rollelegitimationsoplysninger, der hentes fra IMDS, bærer de tilladelser, som den pågældende rolle har; hemmelighedsmanager:Listehemmeligheder (og enhver opfølgende HentHemmeligVærdi) udvider det til at omfatte gemte applikationshemmeligheder. Miljøvariable dumps indeholder ofte registreringstokens, database-URL'er og API-nøgler. I en CI- eller containerkontekst – præcis hvad gaten vælger – er en enkelt transitiv installation af en af ​​disse pakker nok til at lække det materiale.

Ektoplasma passer ind i et mønster, vi fortsat ser: nyttelast under installation, der griber efter cloud-metadata og administrerede hemmeligheder i stedet for lokale filer, og som kun aktiverer sig selv til at blive angrebet i miljøer med høj værdi. To defensive observationer følger.

  • Formen er synligEn npm/PyPI installationskrog, hvis kaldgraf når både en cloud secrets API (aws hemmelighedschef, gcloud-hemmeligheder, AZ-nøglehvælving) eller IMDS-adressen og en netværksudgangssink er et smalt mønster med højt signal — det forekommer næsten aldrig i et legitimt livscyklusscript. Statisk flowanalyse kan markere det uden at være afhængig af et specifikt domæne eller IP-adresse.
  • Miljøhærdning sløver den. Håndhævelse af IMDSv2 med en hopgrænse på 1 forhindrer containerarbejdsbelastninger i at nå instansmetadata; at scope IAM-roller til færrest rettigheder begrænser eksplosionsradiusen for enhver legitimationsoplysninger, der lækker; og at køre installationer med –Ignorér-scripts I CI fjerner install-hook-vektoren helt for pakker, der ikke har brug for den.

For forsvarere er de praktiske kontroller: alarm om udgående forbindelser fra build/CI-containere til offentlige IP'er, der ikke er på tilladelseslisten, under npm installere; hold øje med IMDS-adgang, der stammer fra pakkelivcyklusscripts; og behandl enhver installationshook, der sender til et cloud-CLI, som mistænkelig, indtil det modsatte er bevist.

To yderligere bemærkninger specifikt for denne klynge. For det første, fordi aktivering er gated til containermiljøer, kan en pakke, der ser inert ud, når den kontrolleres på en arbejdsstation, stadig være live i produktion - kontrollen skal reproducere containerens værtsnavn og stibetingelser eller læse kildekoden direkte i stedet for at stole på "Jeg installerede den, og der skete ikke noget." For det andet betyder brugen af ​​en offentlig anmodningsinspektionstjeneste som en beacon-indsamler, at nogle af de eksfiltrerede data kan gendannes til hændelsesrespons: en organisation, der finder en af ​​disse pakker i sit afhængighedstræ, kan ræsonnere om, hvad en vellykket beacon ville have indeholdt ud fra nyttelastens indsamlingslogik, og bør rotere eventuelle IAM-rollelegitimationsoplysninger, registreringsdatabasetokens og administrerede hemmeligheder, der var tilgængelige fra det berørte build- eller runtime-miljø. Rotation af legitimationsoplysninger, ikke fjernelse af pakke, er den operative afhjælpning, når en installation er kørt.

sca-tools-software-kompositionsanalyseværktøjer
Prioriter, afhjælp og sørg for dine softwarerisici
Få din gratis konto.
Der kræves ikke noget kreditkort.

Sikr din softwareudvikling og -levering

med Xygeni-produktsuite