TL; DR
Multzo bat bost npm pakete, bi kontu-helbidetan argitaratua, bidalia postinstall hodeiko kredentzialak ostalariarengandik irakurtzen eta kaxatik kanpo bidaltzen dituen kakoa. Paketeek mamu eta pirata izenak dituzte — coral-wraith, ecto-corsair-whisper-6f3b9, ecto-corsair-flag-x9m4, ecto-rust-read-f3a9c1, ecto-nightly-spirit — eta biltzen duten guztia faltsu bihurtzen dute ecto_module: YAML manifestua transmititu aurretik. Klusterra honela jarraitzen dugu Ektoplasma.
Karga ingurune zehatz bat detektatzen duenean bakarrik exekutatzen da: izena duen ostalari bat. 12 karaktereko kate hamaseitarra eta lan-direktorio bat azpian /app/node_modules — edukiontzi batean kokatutako eraikuntza edo CI langile baten forma. Ate hori igarotzen denean, kakoak kontsulta egiten dio AWS instantziaren metadatuen zerbitzua (IMDSv2) IAM rolaren kredentzialetarako, zerrendatzen ditu AWS Sekretuen Kudeatzailea hiru eskualdetan zehar, ingurune-aldagaiak botatzen ditu, fitxategiak irakurtzen ditu azpian /app, eta bandera harrapatzeko kateak bilatzen ditu. Ondoren, emaitza bi modutara kanporatzen du: baliza batetik... webhook.site biltzailea eta manifestu bat IP gordinaren amaierako puntu batera PUT, localhost-first ordezkoen zerrenda batekin.
Geroagoko paketeen deskribapenek "verdaccio hornidura-katearen probak egiteko CTF karga" diote. Autodeskribapen hori behatzeko moduko gertakari gisa salatzen dugu. Portaera bera —IP publiko baterako irteera zuzena, benetako IMDS kredentzialen irakurketak, benetako Secrets Manager deiak— dena da, etiketa edozein dela ere, eta bertsio hauek gaiztotzat sailkatu izanaren arrazoia da.
Izen bat multzoan, coral-wraith, ez zen argitalpen bakar batean gelditu. Ordu gutxitan dozenaka bertsio berri argitaratu zituen bata bestearen atzetik — 1.0.0 igotzen 6.0.0 — eta izen bereko aurreko lasterketa batek puztutakoak erabili zituen 9999.0.x bertsio zenbakiak, forma klasikoa mendekotasun-nahasmen saiakeraNahasketa horren zehar, karga nabarmen heldu zen: ostalarien zenbaketa-baliza bakarretik AWS kredentzialen ardatz oso batera, bere helburu-helburutik kanpo isil mantentzen duten ingurune-egiaztapenekin bilduta.
| Paketeak | 5 izen; coral-wraith bakarrik berrargitaratua dozenaka bertsiotan |
| ekosistema | NPM |
| Instalatu bektore | postinstall bizi-zikloaren gidoia |
| Helburu nagusia | AWS IAM rolaren kredentzialak + Secrets Manager sekretuen balioak, ingurune aldagaiak, /app fitxategiak |
| Kanporatzea | webhook.site baliza + IP gordina C2 PUT |
| Abiarazle-atea | 12 hexadecimal ostalari-izena + /app/node_modules cwd, gehi testuinguru horretatik kanpoko karga kentzen duen ingurune-egiaztapen bat |
| Larritasuna | altua — hodeiko kredentzialak eta kudeatutako sekretuak dibulgatzea hemendik edukiontzietan oinarritutako eraikuntza eta exekuzio inguruneak |
Erasoaren anatomia
Klusterreko pakete guztiak modu berean eraikitzen dira: ia hutsik dagoen pakete bat aurkibidea.js (modulua.esportazioak = {}), lerro bakarreko paketea.json gidoia — "postinstalazioa": "postinstalazioa.js nodoa" — eta karga barruan postinstall.jsPaketea instalatzea nahikoa da kakoa exekutatzeko; ez da inportaziorik edo deirik behar.
Helburu atea. Ezer egin aurretik, ekto-familiako kargak ingurua egiaztatzen du:
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 12 hexadecimaleko hostname bat da Dockerrek edukiontzi bati esleitzen dion forma lehenetsia, eta /aplikazioa/nodo_moduluak ohiko edukiontzi barruko instalazio-bide bat da. Hirugarren klausulak baztertu egiten du bideak sandbox bidezko erauzketa-direktorio baten itxura badu. Ondorio garbia da karga garatzaileen ordenagailu eramangarri batean edo analisi-sandbox batean inaktibo geratzen dela eta edukiontzi batean kokatutako eraikuntza- edo exekuzio-langile baten barruan bakarrik aktibatzen dela —hodeiko kredentzial biziak eramateko aukera gehien duen ingurune mota. Klusterreko lehen paketea, koral-mamua, ez du halako aterik eta bere bilduma (sinpleagoa) baldintzarik gabe exekutatzen du.
BildumaAtea igarotzean, kakoa kanporatzen da exekutatuFileSync("/bin/sh", ["-c", ...]) eta komando konposatu bakarra exekutatzen du, honako ordena honetan:
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) 1etik 3ra bitarteko urratsak IMDSv2 berreskuratze testuliburuko bat dira: eskatu saio-token bat, eta erantsi gisa X-aws-ec2-metadatu-tokena goiburua instantziaren IAM rola eta rol horren aldi baterako sarbide-gakoak ateratzeko. IMDSv2 inplementatzeko aukera, IMDSv1 sinpleago autentifikatu gabearen ordez. GET aipatzekoa da — horrek esan nahi du karga tokenetan oinarritutako metadatuetarako sarbidea behar duten instantzietan ere funtzionatzen duela, hau da, AWS-k gomendatutako gogortzea. 3. urratsak itzulitako kredentzialak iraupen laburrekoak dira Sarbide-giltza/Sarbide-giltza sekretua/Token instantziaren rolari lotutako hirukoteak; rol horrek egin dezakeen guztia, gako horien jabeak kredentzialaren bizitza osoan egin dezake.
4-6 urratsek ikuspegia zabaltzen dute. env zabortegiak eraikuntza edo exekuzio-prozesuak heredatu duen edozer jasotzen du — praktikan, hemen egoten dira erregistroko tokenak, datu-baseko konexio-kateak eta API gakoak gehienetan. / aplikazioa Fitxategi-ibilaldiak kanpoko hamabost aplikazio-fitxategi irakurtzen ditu gehienez nodo_moduluak, gainazaleko konfigurazioa ager dezakeena, .env fitxategiak edo iturburua. 6. urratseko deiak aws secretsmanager zerrenda-sekretuak hiru eskualdetan; 1-3 urratsetan lortutako kredentzialak dira dei horiek autentifikatzen dituztenak, beraz, IMDS irakurketa eta Secrets Manager zenbaketa-katea eskalatze bakarrean elkartzen dira: instantzia-rola → kudeatutako sekretuen inbentarioa. 7. urratsa bandera harrapatzearen markoari keinu bat da — noiz HTB{…} Bandera aurkitzen bada, bere kabuz bidaltzen da, bestela, bildutako tanta gordina lau zatitan banatu eta bidaltzen da.
Klusterreko bertsio berriek eskalatzea gehiago eramaten dute. Inbentario batean gelditu beharrean, IMDS erantzuna aztertzen dute, aldi baterako gakoak esportatzen dituzte... AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN ingurune-aldagaiak, baieztatu identitatea honekin aws sts deitzailearen identitatea lortu, eta gero itzulitako sekretu guztiak errepikatu zerrenda-sekretuak telefonora deituz aws secretsmanager lortu-sekretuaren-balioa bakoitzean — eduki sekretua berreskuratuz, ez bakarrik haien izenak. Bertsio berdinek prozesu-ordezkatutako bandera binarioak ere irakurtzen dituzte (/irakurketa-bandera eta lagunak) eta saiatu zama-garraioa azpian aurkitutako edozein Rust proiekturen aurka / aplikazioa, hodeiko kredentzialen haratago uzta zabalduz eraikuntza-inguruneak agerian uzten duen edozein gauzatara.
Bertsio berri hauek ere modu oldarkorragoan ateratzen dira. 12 hexadecimal-hostname-az gain eta /aplikazioa/nodo_moduluak egiaztapenetan, kargak pakete-erregistroaren konfigurazio aktiboa eta lan-direktorioaren bidea ikuskatzen ditu eta isilean ixten da analisi edo ispilu testuinguru bat adierazten dutenean, helburu aktibo bat baino. Efektu konbinatuak ikuskapen-ingurune gehienetan behagarririk egiten ez duen karga bat da eta bere bilduma osoa benetako edukiontzi-ostalari batean dagoela epaitzen duen lekuan bakarrik exekutatzen du.
EsfiltrazioaBildutako datuak bi kanaletatik irteten dira ostalaritik. Lehenik, baliza bat POST finko batera. webhook.gunea biltzailea, hostname, UID numerikoa, lan-direktorioa eta bildutako 120 KB-ko datuak daramatzana. Bigarrenik, datuak YAML "modulu manifestu" faltsu batean sartzen dira eta PUT to /api/moduluak/ helburu zerbitzari batean:
ecto_module: name: "<flag-or-chunk-0>" version: "1.0.0" power_level: "<chunk-1>" ship_deck: "<chunk-2>" cargo_hold: "<chunk-3>" Manifestu eremuen izenak (potentzia_maila, itsasontzi_kubierta, zama-hobi) apaingarriak dira — lapurtutako datuak kate-balioen barruan doaz, eta horregatik sareko monitore batek pakete-erregistroko manifestu-igoera onbera bat ikusten du, datu-zabortegi ageriko baten ordez. Beacon kanalak gehiago darama: POST gorputza webhook.gunea ostalari-izena, UID numerikoa, lan-direktorioa eta bildutako blob-aren 120 KB arte barne hartzen ditu, beraz, baliza arrakastatsu bakar batek ere ikuspegi osoa ematen du. webhook.gunea eskaera-ikuskapen zerbitzu doakoa da; biltzaile gisa erabiltzeak esan nahi du operadoreak ez duela inoiz kanal horretarako berezko azpiegitura jasotzeko beharrik izango, eta erregistratutako eskaerak zerbitzuaren zakarrontzian geratzen direla.
Manifestua PUT hainbatekin hasten den ordezko zerrenda bat ibiltzen da 127.0.0.1/localhost portuak eta gero hiru helbide publikoetara erortzen da `-n154.57.164.0/24` barrutia, 2xx egoerarekin erantzuten duen lehenengo amaieran geldituz. Localhost-first ordena "verdaccio testing" auto-deskribapenarekin bat dator (loopback-eko erregistro lokala), baina IP publikoko ordezkoek esan nahi dute datuak host-etik irteten direla loopback-ak entzuten ez duenean — hau da, egilearen proba-plataforma ez den edozein makinatan.
Timeline
Klusterrak gaitasun-hazkunde inkrementala erakusten du, jaitsiera bakarra baino. Behatutako portaeraren arabera ordenatzen dugu, ez argitalpen-hormako erlojuaren arabera:
| Praktikak | Paketeak / Bertsioak | Behavior |
|---|---|---|
| Goiztiarra | coral-wraith 9999.0.x | Mendekotasun-nahasmen saiakera batekin bat datozen bertsio-zenbaki puztuak; instalazio-garaiko zenbaketa eta kanporatzea |
| Seed | coral-wraith 1.0.0 | instalazio ostekoak id/env/flag fitxategiak biltzen ditu; PUT bakarra 154[.]57[.]164[.]71:30782, markatzailea ECT-472839 |
| Iterazio azkarra | coral-wraith 1.0.1 → 6.0.0 | Ordu gutxitan dozenaka askapen; kargak irabazten du isAppWorker() atea, IMDSv2 kredentzialen erauzketa, osoa get-secret-value Pibota, erregistroaren/bidearen ingurunearen egiaztapena eta hustubide bikoitzeko markatzaileak |
| Izen paraleloak | ecto-corsair-whisper-6f3b9 1.0.14–1.0.18 | Karga erabilgarri bera; webhook.site baliza eta hainbat amaiera-puntuko ordezko zerrenda |
| Aldaera | ecto-rust-read-f3a9c1 1.0.1–1.0.2 | Konketa-markatzaile gehigarriak gehitzen ditu ECT-987654, ECT-654321, ECT-839201 |
| Aldaera | ecto-corsair-flag-x9m4 1.0.0, ecto-nightly-spirit 1.1.0 | Karga bera, C2 eta baliza bera |
Klusterraren ezaugarri nagusia argitalpen-kadentzia da: pakete eta bertsio baten ordez, izen bera behin eta berriz argitaratzen da bata bestearen atzetik, bertsio bakoitza aurrekoaren aldaera txiki bat izanik, eta karga bera daramaten izen ezberdineko anai-arreba batzuekin batera. Barruan... xuxurla familia kodea bi hatz-marka estutan banatzen da —multzo batek bi detekzio kritiko eragiten ditu, beste hiru (fitxategi-irakurketa hondo gehigarri bat)— baina biak karga berera ebazten dira; aldea kodearen desbideratzea da, ez portaera-sardexka bat. Bertsioak xuxurla aztertutako tartetik kanpo (idazteko unean gutxienez 1.0.25era arte) erregistroan zuzenean ikusi ziren, eta koral-mamua izenak bere bertsio-eskailera igotzen jarraitu zuen leiho beraren gainetik.
Konpromisoaren adierazleak
Beheko adierazle guztiak diskoan dagoen paketearen iturburutik atera dira. Sareko adierazleak desaktibatuta daude.
Sarea
| Adierazlea | Role |
|---|---|
hxxp://154[.]57[.]164[.]71:30782 | C2 PUT helburua (coral-wraith) |
hxxp://154[.]57[.]164[.]80:30543 | C2 PUT ordezkoa (ecto-*) |
hxxp://154[.]57[.]164[.]82:31250 | C2 PUT ordezkoa (ecto-*) |
hxxp://154[.]57[.]164[.]71:31289 | C2 PUT ordezkoa (ecto-*) |
hxxps://webhook[.]site/602a4c72-7033-4e28-92ea-dc66e59206e5 | Faroen biltzailea |
169[.]254[.]169[.]254/latest/... | IMDSv2 kredentzialaren irakurketa (helburuaren aldekoa, AWS metadatuak) |
Portaera/fitxategia
| Adierazlea | Role |
|---|---|
"postinstall": "node postinstall.js" | Instalatu bektore |
ecto_module: YAML honekin power_level / ship_deck / cargo_hold gakoak | Exfil manifestu eskema |
Harraska-markatzaileak ECT-472839, ECT-987654, ECT-654321, ECT-839201 | C2 bide segmentua /api/modules/<marker> |
isAppWorker() atea: ostalaria /^[0-9a-f]{12}$/, cwd-k dauka /app/node_modules | Aktibazio-baldintza |
aws secretsmanager list-secrets baino gehiago us-east-1, eu-west-1, eu-central-1 | Sekretuen zenbaketa |
HTB{...} regex scrape | Bandera-uzta harrapatuz |
Fitxategien hash-ak (sha256, analisi-garaian jasota)
| File | sha256 |
|---|---|
coral-wraith/postinstall.js | ce5ff035cfdfed1d0015446424b352c27b66bcb77e9fdb0a51e4245199146824 |
ecto-corsair-whisper-6f3b9 1.0.18/postinstall.js | b58432acba376aa6976f0490d9a1c04257ccdbc856d8390260c50322d63e31c3 |
Atribuzioa eta behatutako portaera
Bost paketeen izenak bi npm kontu-helbideren pean argitaratu ziren, baina nahikoa azpiegitura partekatzen dute kluster bakar gisa tratatzeko: berdina ekto_modulua manifestu eskema, berdina ECT-472839 lehen mailako hustubideko markatzailea, berdina webhook.gunea bildumagilearen IDa eta C2 amaiera-puntuak berdinak dira 154.57.164.0/24` blokea. Hazien paketea (`koral-mamua`, sinpleagoa eta aterik gabekoa) eta, beraz, atedun ekto-familia tresna-sorta bakarreko iterazio gisa irakurtzen da, ahalegin independente gisa baino.
Paketeek, bertsio berrietan, honela deskribatzen dute beren burua: "CTF karga verdaccio hornidura-katearen probak egiteko." Etiketa hori behatzeko moduko gertakari gisa azaleratzen dugu eta ez dugu helburuaren inguruko aurkikuntza gisa berresten. Kodeak egiten duena argia da eta etiketatuta dagoen moduarekiko independentea da: IAM rolaren kredentzialak instantziaren metadatuen zerbitzutik irakurtzen ditu, hiru AWS eskualdetan kudeatutako sekretuak zerrendatzen ditu eta emaitzak IP publiko bati eta hirugarrenen webhook biltzaile bati transmititzen dizkio. Benetako loopback proba-arnes batek ez luke IP publikoaren ordezko zerrendarik, IMDS kredentzialen irakurketarik edo eskualde arteko Secrets Manager deirik beharko. Irteera eta kredentzialen irismena errealak direnez, bertsio ateak gaiztotzat sailkatu ziren.
Edukiontzi-bakarrik dagoen atea da ezaugarri operatiboki nabarmenena. Saihesbide neurri bat da —ordenagailu eramangarrietan eta analisi-sandboxetan isilpean egotea— eta helburu neurri bat, benetako IAM rol bat eta sekretu biziak egoteko aukera gehien duten lekuetan bakarrik aktibatzen dena. Pakete hauek sandbox generiko batean exekutatzen dituzten analistek ez lukete ezer ikusiko; portaera Docker estiloko ostalari-izen baten eta edukiontzi barruko instalazio-bide baten pean bakarrik agertzen da.
Eragina, joerak eta defendatzaileentzako orientabideak
Hemen esposizioa hodeiko kredentzialen eta sekretuen dibulgazioa da, eraikuntza eta exekuzio-denbora edukiontzien barruan. IMDStik ateratako IAM rol-kredentzial batek rol horrek dituen baimenak ditu; secretsmanager:ZerrendaSekretuak (eta ondorengo edozein LortuBalioSekretua)-k gordetako aplikazioen sekretuetara zabaltzen du hori. Ingurune-aldagaien zabortegiek maiz erregistroko tokenak, datu-baseko URLak eta API gakoak eramaten dituzte. CI edo edukiontzi testuinguru batean — hain zuzen ere, ateak hautatzen duen horretarako — pakete horietako baten instalazio trantsizio bakarra nahikoa da material hori filtratzeko.
Ectoplasm ikusten jarraitzen dugun eredu bati jarraitzen dio: instalazio-garaiko kargak, hodeiko metadatuetara eta kudeatutako sekretuetara jotzen dutenak, tokiko fitxategien ordez, eta balio handiko inguruneetan bakarrik aktibatzeko aktibatzen direnak. Bi behaketa defentsibo jarraitzen dute.
- Forma hauteman daiteke.. npm/PyPI instalazio-hook bat, zeinaren dei-grafoak cloud secrets API batera iristen den (AWS SecretsManager, gcloud-eko sekretuak, az keyvault) edo IMDS helbidea eta sareko irteerako hustubidea seinale handiko eredu estua da — ia inoiz ez da gertatzen bizi-zikloko script legitimo batean. Fluxu estatikoaren analisia domeinu edo IP zehatz baten menpe egon gabe markatu dezake.
- Ingurunea gogortzeak ahultzen du. IMDSv2 1eko jauzi-mugarekin betearazteak edukiontzi-lan-kargek instantziaren metadatuetara iristea eragozten du; IAM rolak pribilegio gutxienera mugatzeak ihes egiten duen edozein kredentzialaren eztanda-erradioa mugatzen du; eta instalazioak exekutatzeak... –ignore-script-ak CI-n install-hook bektorea erabat kentzen du hura behar ez duten paketeetarako.
Defendatzaileentzat, egiaztapen praktikoak hauek dira: build/CI edukiontzietatik baimendu gabeko zerrendako IP publikoetara irteerako konexioen alerta npm instalatu; paketeen bizi-zikloko scriptetatik sortutako IMDS sarbideak zaindu; eta hodeiko CLI batera bidaltzen den edozein instalazio-hook susmagarritzat hartu, kontrakoa frogatu arte.
Kluster honi buruzko beste bi ohar espezifiko. Lehenik eta behin, aktibazioa edukiontzietan banatutako inguruneetara mugatuta dagoenez, lan-estazio batean egiaztatzean geldirik agertzen den pakete bat ekoizpenean ere egon daiteke — egiaztatzeak edukiontziaren ostalariaren izena eta bidearen baldintzak erreproduzitu behar ditu, edo iturburua zuzenean irakurri, "Instalatu dut eta ez da ezer gertatu" esan beharrean. Bigarrenik, eskaera-ikuskapen zerbitzu publiko bat beacon biltzaile gisa erabiltzeak esan nahi du kanporatutako datu batzuk berreskuragarriak izan daitezkeela intzidenteei erantzuteko: bere mendekotasun-zuhaitzean pakete horietako bat aurkitzen duen erakunde batek beacon arrakastatsu batek zer edukiko lukeen arrazoitu dezake kargaren bilduma-logikatik abiatuta, eta IAM rol-kredentzialak, erregistroko tokenak eta kudeatutako sekretuak txandakatu beharko lituzke, kaltetutako eraikuntza- edo exekuzio-ingurunetik eskura zitezkeenak. Kredentzialen errotazioaInstalazio bat exekutatu ondoren konponketa operatiboa ez da paketea kentzea.





