
Falešná podpora jazyka R ve vývojovém prostředí načítala zašifrovaný JavaScript ze Solany a nasazovala moduly pro krádež dat prohlížečů.
Výzkumníci Bitdefenderu objevili škodlivé rozšíření integrovaného vývojového prostředí Windsurf. Nasazuje vícestupňový zlodějský malware pro NodeJS a jako infrastrukturu pro doručení kódu používá blockchain Solana.
Rozšíření se vydávalo za podporu jazyka R pro Visual Studio Code. Z blockchainových transakcí získává zašifrovaný JavaScript, spouští jej pomocí funkcí běhového prostředí NodeJS a ukládá zkompilované doplňky pro získávání dat z Chromia. Současně zajišťuje přetrvání v systému pomocí skryté naplánované úlohy PowerShellu.
Existuje oficiální a legitimní rozšíření REditorSupport. Útočník pravděpodobně zvolil velmi podobný název právě kvůli záměně.
Útok výslovně vynechává ruské systémy a míří na vývojářská prostředí. Útočníci tak mohou získávat zvlášť cenné přístupové údaje.
Hlavní zjištění
- Falešné rozšíření pro vývoj v R instalované do Windsurf IDE spouští malwarovou infekci.
- Skutečnou funkci skrývalo a svůj kód dešifrovalo až po instalaci, aby ztížilo detekci.
- Škodlivý kód získávalo z blockchainu Solana místo tradičních řídicích serverů. Vyřazení infrastruktury je tím výrazně obtížnější.
- Před útokem kontrolovalo, zda je oběť v Rusku, a v takovém případě se ukončilo.
- Cílem je odcizení uložených hesel, relačních cookies a dalších citlivých dat z prohlížečů založených na Chromiu.
- Pro přetrvání vytváří skrytou úlohu Windows, která jej znovu spouští přes přibalené prostředí NodeJS.
- Kampaň záměrně cílí na vývojáře, kteří často disponují privilegovaným přístupem, API klíči a dalšími hodnotnými údaji.
Objevení incidentu a první upozornění
Vyšetřování začalo poté, co Bitdefender EDR na firemní stanici vytvořil několik detekcí souvisejících s procesem windsurf.exe.
Uživatel si nainstaloval rozšíření Windsurfu pro vývoj v jazyce R, tedy prostředí srovnatelné s MATLABem. Rozšíření neslo název:
reditorsupporter.r-vscode-2.8.8-universal
Infekce se neopírala o samostatný spustitelný soubor. Běžela uvnitř důvěryhodného ekosystému rozšíření IDE, takže škodlivá logika přetrvávala navzdory detekcím spojeným s procesem hlavní aplikace.
Škodlivé rozšíření v adresáři .windsurf
Vyšetřovatelé ručně prozkoumali adresář rozšíření Windsurfu:
.windsurf/
V tomto umístění, kam IDE ukládá všechna rozšíření, identifikovali podezřelý balíček. Obsahoval neobvyklý blok JavaScriptu dešifrující vložený kód. Konečné škodlivé funkce v něm přímo nebyly: fungoval jako zavaděč.
Po dešifrování se objevila druhá komponenta JavaScriptu. Před dalším pokračováním kontrolovala prostředí.
Dešifrovaný zavaděč a profilování systému
Prvním úkonem bylo profilování systému. Kód získal aktuální uživatelské jméno, prověřil proměnné prostředí, jazykové a regionální nastavení i časové pásmo a vypočítal čas UTC.
Výslovně hledal ruské ukazatele. Kontroloval jazykové značky a slovo „Russian“, porovnával časové pásmo se známými ruskými regiony Europe/Moscow, Europe/Kaliningrad, Europe/Samara, Asia/Yekaterinburg, Asia/Omsk, Asia/Krasnoyarsk, Asia/Irkutsk, Asia/Yakutsk, Asia/Vladivostok, Asia/Magadan, Asia/Kamchatka, Asia/Anadyr a MSK a ověřoval posun UTC v rozmezí +2 až +12.
function _isRussianSystem() {
let isRussianLanguage = [os.userInfo().username, process.env.LANG, process.env.LANGUAGE, process.env.LC_ALL, Intl.DateTimeFormat().resolvedOptions().locale].some(info => info && /ru_RU|ru-RU|Russian|russian/i.test(info)),
timezoneInfo = [Intl.DateTimeFormat().resolvedOptions().timeZone, new Date().toString()],
russianTimezones = ["Europe/Moscow", "Europe/Kaliningrad", "Europe/Samara", "Asia/Yekaterinburg", "Asia/Omsk",
"Asia/Krasnoyarsk", "Asia/Irkutsk", "Asia/Yakutsk", "Asia/Vladivostok", "Asia/Magadan", "Asia/Kamchatka", "Asia/Anadyr", "MSK"
],
isRussianTimezone = timezoneInfo.some(info => info && russianTimezones.some(tz => info.toLowerCase().includes(tz.toLowerCase()))),
utcOffset = -new Date().getTimezoneOffset() / 60,
isRussianOffset = utcOffset >= 2 && utcOffset <= 12;
return isRussianLanguage && (isRussianTimezone || isRussianOffset)
}
name(_isRussianSystem, "_isRussianSystem");Pokud systém splnil tyto podmínky, běh se okamžitě ukončil.
Toto záměrné vynechání ruských systémů odpovídá provozním pojistkám, které se typicky spojují s finančně motivovanými kyberzločineckými skupinami snažícími se vyhnout pozornosti domácích úřadů.
Zneužití Solana RPC a vzdálené získávání kódu
Protože rozšíření běží v prostředí NodeJS bez sandboxu, může volně komunikovat s operačním systémem i sítí.
Po úspěšném dokončení kontrol malware odesílal požadavky POST na:
https://api.mainnet-beta.solana[.]com
Volal metodu Solana JSON-RPC:
getSignaturesForAddress
Namísto tradičního řídicího serveru C2 použil Solanu jako decentralizovanou infrastrukturu. Dotazoval se na blockchainové transakce a získával zakódovaná data vložená do jejich metadat.
Po dokončení požadavku obdržel datové buffery s fragmenty JavaScriptu. Dekódoval je a připravil ke spuštění.
Dynamické spouštění v NodeJS bez sandboxu
Získaný obsah tvořil JavaScript v base64 s dalšími komponentami zašifrovanými AES. Zavaděč škodlivé běhové prostředí rekonstruoval dynamicky.
Jelikož rozšíření Windsurfu běží v NodeJS bez přísné izolace, malware získal přímý přístup k souborovému systému a mohl bez omezení načítat nativní moduly.
Nativní doplňky .node a získávání dat z Chromia
Po dynamickém spuštění malware uložil soubory do:
AppData\Local\Temp\<random_string>\
Pozorované soubory zahrnovaly:
w.node
c_x64.node
index_ia32.node
DllExtractChromiumSecrets.dll
Jde o knihovny DLL, které NodeJS načítá jako soubory .node.
const addon = require('C:/Users/<USER>/AppData/Local/Temp/<Random_String>/c_x64.node');
const result = addon.extractBrowserData(browser, outputFile, showAll, decryptedData, profile);Výzkumník potvrdil, že tyto komponenty fungují jako zloději přihlašovacích údajů.
Tyto nativní moduly umožňují:
- Přímou práci s profily prohlížečů.
- Získání uložených přihlašovacích údajů.
- Načtení cookies a relačních tokenů.
- Přístup k šifrovaným tajným údajům Chromia.
PowerShell a přetrvání pomocí naplánované úlohy
Po nasazení nativních zlodějských modulů malware vyvolal PowerShell, aby zajistil přetrvání v systému.
PowerShellová komponenta skryla konzolové okno, využila volání Win32 API přes Add-Type a vytvořila naplánovanou úlohu s názvem:
UpdateApp
Původní text zde uvádí spuštění úlohy, ale neobsahuje další příkazový řádek.
Úloha byla nastavena ke spuštění při startu s nejvyššími oprávněními a obcházením omezení zásad spouštění.
Skript také pracoval s následujícím klíčem registru a odstraňoval stopy své přítomnosti:
HKCU:\Software\Microsoft\Windows\CurrentVersion\Run
Odstranil záznamy odpovídající určitým vzorcům spouštění a znovu nastavil mechanismy přetrvání.
Škodlivý proces tak pokračoval i po zavření IDE.
Jako poslední krok zajištění přetrvání skript spustil:
C:\Users\<user>\AppData\Roaming\node_x86\node\node.exe
S argumentem:
C:\Users\<user>\AppData\Roaming\zplnUtG\index.js
Infekce tak dokázala samostatně pokračovat i přes restarty systému.
Celý řetězec infekce
- Stažení rozšíření Windsurfu.
- Spuštění škodlivého balíčku NodeJS.
- Spuštění PowerShellu.
- Vytvoření naplánované úlohy pro přetrvání.
- JavaScript zakódovaný v base64.
- Kód zašifrovaný AES.
- Dynamické spuštění.
- Vzdálené získání kódu ze Solany.
- Práce s prohlížečem pomocí nativních knihoven .node.
Závěr
Incident ukazuje, jak se útočníci stále více zabydlují v důvěryhodných vývojářských nástrojích místo spoléhání na tradiční způsoby doručení.
Zamaskováním krádeže přístupových údajů za zdánlivě legitimní rozšíření R získali běh uvnitř vývojářova IDE, stáhli zašifrovaný kód ze Solany a nasadili nativní moduly schopné vytahovat citlivá data prohlížečů.
Záměrné vynechání ruských systémů dále naznačuje finančně motivovanou kampaň s provozními pojistkami.











