JavacDoor, malware Maven, který běží během kompilace

JavacDoor: Artefakt Mavenu, který běžel během kompilace, nikoli během instalace

TL, DR

Artefakt Maven Central publikovaný jako io.github.davidtimur:c2-lab vydáno devět verzí, z nichž osm provedlo datovou zátěž pro vzdálený přístup během kompilace jakéhokoli následného projektu, který umístil soubor JAR na cestu anotace-procesoru. Žádný aplikační kód jej nemusel importovat. Žádný řádek zdrojového kódu se na něj nemusel odkazovat. Nebyl k dispozici žádný instalační skript, žádný ekvivalent po instalaci a žádný hook životního cyklu jakéhokoli druhu, který by nástroje mohly zkontrolovat.

Vektor provedení je jeden 46bajtový soubor uvnitř JAR souboru: registrace poskytovatele služeb Java, která pojmenovává třídu implementující javax.annotation.processing.ProcessorKompilátor Javy takové registrace automaticky vyhledá. Jakmile jsou nalezeny, javac vytváří instanci a spouští třídu jako běžnou součást kompilace. To znamená, že běhové prostředí datové části je sestavovací stroj v okamžiku, kdy sestavovací stroj dělá jedinou věc, pro kterou existuje.

V devíti verzích byl kanál pro příkazy a řízení třikrát přestavěn: operátorem zadaná URL zpětného volání, poté reverzní shell přes TCP tunel ngrok a nakonec kanál pro dotazování HTTP, jehož cesty se posunuly ještě dvakrát. Finální verze nainstalovala jako výchozí JVM správce důvěryhodnosti TLS bez operací. přijetí jakéhokoli certifikátu po dobu kompilace.

Artefakt nesl ve svém vlastním POM a licenci MIT slova „C2 Lab Payload“. Po celou dobu, kdy jsme ho pozorovali, byl aktivní na Maven Central. byl od té doby odstraněn spolu s celým svým io.github.davidtimur skupina.

Anatomie: kompilátor jako spouštěcí engine

V Javě existuje framework pro zpracování anotací, takže knihovny mohou generovat kód během kompilace – mechanismus, který stojí za Lombokem, Daggerem a dlouhým seznamem nástrojů ORM a serializace. Procesor se ohlásí pomocí souboru s prostým textem uvnitř JAR souboru:

META-INF/services/javax.annotation.processing.Processor

Obsah daného souboru v každé dotčené verzi, doslovný i úplný:

io.github.davidtimur.c2lab.C2Processor

Soubor je bajtově identický ve verzích 1.0.1 až 1.0.8, md5. 7d2a08a5c8869a47eea9fa62487dfbe4. Verze 1.0.0 ji neobsahuje.

Kdy jávský Spuštění prohledá cestu k anotačnímu procesoru a vyhledá tyto položky služeb a načte nalezené položky. Nic v kompilovaném projektu nemusí zmiňovat procesor, cokoli anotovat ani cokoli konfigurovat. Přítomnost v cestě je dostatečná. Toto je vlastnost, která odlišuje JavacDoor od vzorů dodavatelského řetězce, na kterých je postavena většina nástrojů:

Vzor spoušť Viditelné jako
instalace npm hooku npm install scripts.postinstall v manifestu
Datová část Pythonu při importu první import modulu příkaz na úrovni modulu ve zdrojovém kódu
JavacDoor javac na jakémkoli následném projektu název souboru pro registraci služby

Instalační hook je deklarace v manifestu a manifest je první věc, kterou si kdokoli přečte. Importní datový soubor se alespoň nachází v čitelném zdrojovém kódu. Registrace služby není ani jedno: je to název souboru plus jeden řádek pojmenující třídu a chování se nachází v kompilovaném bajtkódu o další adresář.

Třída payload sama o sobě provádí průzkum hostitele pomocí shell-outu. Konstantní fondy kompilovaných tříd obsahují / Bin / sh, whoami, uname -a, pwd na cestě Unixu a tasklist na cestě Windows, spolu s redirectErrorStream pro sloučení chybového výstupu podřízeného procesu do zachyceného streamu. Dvě šablony JSON přenášejí výsledky z hostitele – registrační maják:

{"host":"%s","os":"%s","user":"%s","dir":"%s"}

osídleno z hostname příkaz a název_os, user.name, a user.dir vlastnosti systému a zpětné volání výsledku:

{"version":"%s","host":"%s","time":"%s","output":"%s"}  

Značky průběhu ponechané ve vlastním výstupu kompilátoru jsou neobvykle upřímné: [C2] Dokončeno provedení během kompilace, [C2] zpětné volání odesláno → HTTP , [C2] skořepina připojená k .

Devět vydání, tři generace C2

Vydané verze nejsou devíti kopiemi jednoho datového obsahu. Jsou to iterační protokoly a jejich čtení v pořadí ukazuje, že kanál byl přestavěn, zatímco vektor doručení zůstal pevný.

Uvolnění Automaticky se spouští při kompilaci Kanál
1.0.0 ne (žádný servisní soubor) Pouze URL adresa zpětného volání poskytnutá operátorem
1.0.1 ano (zaveden vektor) URL zpětného volání poskytnutá operátorem
1.0.2 ano Reverzní shell, ngrok TCP tunel
1.0.3 ano HTTP kanál, /register /cmd /out
1.0.4 ano HTTP kanál, /register /cmd /out
1.0.5 ano HTTP kanál, /register /poll /out
1.0.6 ano HTTP kanál, /register /poll /out
1.0.7 ano HTTP kanál, /register /cmd
1.0.8 ano Kanál HTTP + ověření TLS zakázáno

V této tabulce stojí za zmínku tři detaily, protože každý z nich mění způsob, jakým by se měla sada artefaktů číst.

Vektor dorazí na 1.0.1, nikoli na 1.0.2. Verze 1.0.0 obsahuje stejnou logiku pro průzkum a zpětné volání, ale nemá žádný servisní soubor ani import anotací; běží pouze tehdy, když je volána. Od verze 1.0.1 je servisní soubor přítomen a kompilované třídy se importují. javax.annotation.processing.SupportedSourceVersionJakékoli hodnocení, které porovnává dvě schválené verze – 1.0.0 a 1.0.2 – správně dochází k závěru, že se něco změnilo, ale chybně identifikuje kde.

Reverzní shell existuje právě v jednom vydání. Verze 1.0.2 obsahuje 0.tcp.ngrok[.]io, řádek protokolu [C2] shell připojený k 0.tcp.ngrok[.]io:19823, interaktivní banner c2-shella terminátor rámce __KONEC__Verze 1.0.3 a novější neobsahují žádné z nich a místo toho se dostanou k hostiteli HTTPS. Žádost o odstranění, která by jmenovala pouze ticketované verze, by odkazovala na nefunkční TCP endpoint, zatímco aktivní HTTP kanál, který byl přítomen v šesti pozdějších verzích, by zůstal nezmíněn.

Finální verze odstraňuje ověřování transportu. Verze 1.0.8 přidává implementaci třídy javax.net.ssl.X509TrustManager jehož metody kontroly certifikátů nic nedělají, ověřovač hostitelského jména s vždy pravdivým názvem registrovaný prostřednictvím setDefaultHostnameVerifier, A důvěřovat všem rutina, která nainstaluje oba jako výchozí hodnoty JVM. Důsledkem je, že po zbytek kompilace JVM přijímá jakýkoli certifikát od jakéhokoli hostitele – nejen pro vlastní provoz dané zátěže, ale i pro cokoli dalšího, co sestavení následně provádí přes TLS.

Kanál HTTP je ve všech šesti verzích, které jej používají, spravován jedním hostitelem: tableful-fervor-crazed.ngrok-free[.]devKaždý požadavek nese hlavičku. ngrok-skip-browser-warning, který potlačuje vsunutou stránku, kterou prohlížečům zobrazují bezplatné tunely ngrok. Sady cest se mezi verzemi mění – /ven zmizí ve verzi 1.0.7 a /cmd střídá se s /hlasování — ale hostitel se nikdy nemění.

Sebevyloučení říká

Každý POM od verze 1.0.1 dále nastavuje argument kompilátoru pro vlastní sestavení artefaktu:

-proc:žádný

Tento příznak zakazuje zpracování anotací. Jeho účinek je zde předemcise: když je projekt obsahující procesor sám zkompilován, procesor se nespustí.

Tento příznak má zcela běžné využití. Projekt, který dodává anotační procesor, se často potřebuje vyhnout jeho použití na sebe během bootstrapu a dokumentace build-tool to přesně doporučuje. Samotný vzato nic nedokazuje.

Dohromady s tím, co procesor dělá, to však popisuje specifickou asymetrii: kód se spouští na počítačích všech, kteří kompilují s artefaktem, a nikoli na počítači, který artefakt sestavuje. Příznak se objevuje ve stejné verzi, která představuje soubor služby – 1.0.1 – a v každé následující verzi. Korelace mezi „verzí, kde začíná provádění za kompilace“ a „verzí, kde je provádění za kompilace lokálně vypnuto“ je nejužitečnějším analytickým signálem v sadě artefaktů a je viditelná v POM v prostém textu bez nutnosti dekompilace.

Všimneme si efektu a u toho se zastavíme. Nic v artefaktech neříká, proč byla vlajka vztyčena.

Zmínku si zaslouží ještě jeden metadata, hlavně proto, aby se s nimi dalo naložit. POM pojmenovává projekt „C2 Lab Payload“, popisuje ho jako „artefakt C2 lab payload“ a licencuje ho MIT. Takovéto sebeoznačení se někdy nabízí jako důkaz, že balíček je výzkumným cvičením.cise spíše než živá hrozba, a občas je tento výklad správný – deklarovaný kanárek bez dosažitelné infrastruktury je jiný objekt než tento. Zde se to netýká. Funkční implantát publikovaný do veřejného repozitáře, dosažitelný pro jakéhokoli uživatele, s odchozí infrastrukturou, která byla třikrát přestavěna v devíti verzích, je živá schopnost bez ohledu na to, jak ji nazývají její metadata. Název v POM nemění nic na tom, co se děje na počítači, který se proti němu kompiluje.

Indikátory pro stavební stroje

Pokud hostitel sestavení kompiluje s tímto artefaktem, důkazy se nacházejí v protokolech sestavení a síťové telemetrii, nikoli v trvalém implantátu na disku – datová část se spustí uvnitř procesu kompilátoru a ukončí se s ním.

V mezipaměti JAR nebo lokálního repozitáře

  • META-INF/services/javax.annotation.processing.Processor pojmenování io.github.davidtimur.c2lab.C2Processor
  • Servisní soubor md5 7d2a08a5c8869a47eea9fa62487dfbe4
  • Třídy pod io/github/davidtimur/c2lab/: C2Processor, C2Task, Taska ve verzi 1.0.8 vnitřní třída Task$1

Výstup ve sestavení

  • [C2] compile-time execution complete
  • [C2] callback sent → HTTP
  • [C2] callback failed:
  • [C2] shell connected to
  • Interaktivní banner c2-shellukončovač rámce __END__

Telemetrie v procesu

  • javac jako rodič /bin/sh -c (Unix) nebo interpret příkazů ve Windows
  • Podřízené příkazy whoami, uname -a, pwd (Unix) nebo tasklist (Windows) nadřazené krokem kompilace

V síťové telemetrii

  • Odchozí TCP do 0.tcp.ngrok[.]io:19823 (verze 1.0.2)
  • HTTPS do tableful-fervor-crazed.ngrok-free[.]dev, cesty /register, /cmd, /poll, /out (verze 1.0.3 až 1.0.8)
  • Záhlaví požadavku ngrok-skip-browser-warning: true
  • Žádost o porovnání těl {"host":...,"os":...,"user":...,"dir":...} or {"version":...,"host":...,"time":...,"output":...}

V konfiguraci

  • Proměnné prostředí CALLBACK, CALLBACK_URLsystémová vlastnost callback.url

Metadata vydavatele

  • Skupina io.github.davidtimuradresa vydavatele davudboi999@gmail[.]compodpisový klíč E520C345EF94423D

Sestavení s verzí 1.0.8 vyžaduje jednu další kontrolu. Protože tato verze instaluje permisivní správce důvěryhodnosti jako výchozí nastavení pro celý JVM, jakékoli TLS připojení vytvořené později ve stejném JVM – rozlišení závislostí, nahrávání artefaktů, krok nasazení – probíhalo bez ověření certifikátu. Provoz z tohoto okna by neměl být považován za ověřený.

Proč kompilované artefakty potřebují odlišné skenování

JavacDoor je užitečný testovací případ, protože vyvrací dva běžné předpoklady najednou a ani jedno selhání není specifické pro nástroje konkrétního dodavatele.

Prvním předpokladem je, že nebezpečný kód se ohlásí v manifestu. Velká část nástrojů pro dodavatelský řetězec je organizována kolem životního cyklu hooks, protože u npm a PyPI je to obvykle místo, kde se akce odehrává. JavacDoor nemá žádný háček. Jeho spouštěčem je soubor registrace služby, jehož název je rozhraní Java a jehož obsah je název třídy. Abyste to zachytili staticky, musíte to ošetřit META-INF/services/javax.annotation.processing.Processor jako samostatný vstupní bod pro provedení, na stejné úrovni jako po instalaci skript — a poté následovat pojmenovanou třídu do bajtkódu. Ekosystémy mají své vlastní mechanismy automatického vyhledávání tohoto tvaru a každý z nich je vstupním bodem, ať už jej nástroje jako jeden vyjmenují, nebo ne.

Druhým předpokladem je, že řetězce se nacházejí ve zdrojových souborech. Pro JAR jsou koncové body, příkazy shellu, šablony JSON a značky protokolů v konstantních poolech. .třída soubory. Nástroje, které grepují text, nic nenajdou – ne proto, že by řetězce byly obfuskované, ale proto, že jsou ve strukturovaném binárním kontejneru, který textový sken neanalyzuje. Každý síťový indikátor v tomto příspěvku vzešel z analýzy konstantního poolu. Jeden z nich je plně vytvořený https:// URL adresa je viditelná uvnitř souboru třídy; textové skenování čitelného obsahu JAR souboru by ji stále neodhalilo. Není zde žádné kódování, které by bylo třeba překonat, pouze formát kontejneru, který je třeba přečíst.

Obě mezery mají stejný tvar: formát artefaktu byl považován za pytel souborů, nikoli za strukturu s definovanou sémantikou. Náprava je nenápadná – analyzujte kontejner, vyjmenujte vlastní vstupní body automatického vyhledávání ekosystému a sledujte je v kompilovaném kódu. Konkrétně pro vektory za sestavení je třetí kontrola levná a překvapivě diagnostická: porovnejte, co artefakt dělá spotřebitelům, s tím, od čeho se sám vyjímá. Artefakt, který registruje procesor za kompilace a současně zakazuje zpracování za kompilace pro své vlastní sestavení, vám o sobě něco řekl ve dvou řádcích prostého textového POM.

Pro týmy, které dnes využívají artefakty Mavenu, následují tři praktická opatření:

  • Cestu anotačního procesoru považovat za hranici provádění. Závislosti, které se tam dostanou, spouštějí kód ve vaší sestavě. Pokud sestava nevyžaduje zpracování anotací, -proc:žádný je stejně užitečné v obraně, jako to zřejmě bylo lokálně zde; tam, kde ano, je třeba explicitně připnout sadu procesorů, místo aby se dědila z cesty tříd kompilace.
  • Podprocesy kompilátoru protokolů. Krok kompilace, který spustí shell, je ve většině projektů anomální a lze na něj triviálně upozornit.
  • Nezacházejte s metadaty jako svědectvím. „Lab“, „test“, „payload“ a „PoC“ v názvu nebo popisu balíčku nepředstavují omezení rozsahu. Dosažitelnost a chování ano.

Artefakt a celá jeho skupina byly odstraněny z Maven Centrální server po našem hlášení; jak cesta k artefaktu, tak i cesta ke skupině nyní vrací chybu 404 a index Centrálního serveru nehlásí žádné odpovídající souřadnice. Tím se tento artefakt uzavře. Neuzavře se vektor, což je zdokumentovaná funkce kompilátoru Java a dostupná pro každého, kdo publikuje soubor JAR.

Reference

Tento příspěvek necituje žádné externí zdroje. Veškeré poznatky jsou statickou analýzou devíti publikovaných souborů JAR, které byly před odstraněním získány z Maven Central. V žádném okamžiku nebyl spuštěn žádný kód z artefaktů.

nástroje pro analýzu složení softwaru SCA
Stanovte priority, opravte a zabezpečte svá softwarová rizika
Získejte svůj bezplatný účet.
Nevyžaduje se žádná kreditní karta.

Zajistěte si vývoj a dodávky softwaru

s produktovým balíčkem Xygeni