Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Adminie… Czy znamy Twoje grzechy? ;-) Sprawdź!
Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Adminie… Czy znamy Twoje grzechy? ;-) Sprawdź!
Badacze bezpieczeństwa z StepSecurity odkryli nową kampanię malware, w której atakujący przejmuje masowo konta programistów na GitHub i wstrzykuje złośliwe oprogramowanie do setek repozytoriów. Pierwszą aktywność odnotowano 8 marca 2026 roku, ale według ustaleń badaczy kampania wciąż trwa i przejmowane są kolejne repozytoria. Kampania – nazwana przez badaczy ForceMemo – wykorzystuje nietypową technikę force-push do ukrywania zmian w repozytoriach.
Atak celuje w projekty Python – w tym aplikacje działające w frameworku Django oraz pakiety PyPI. Malware umieszczane jest w zaciemnionej (obfuskowanej) formie do plików takich jak setup.py, main.py i app.py. Każdy, kto wykona polecenie pip install w katalogu zainfekowanego repozytorium lub sklonuje je i wykona kod, uruchomi malware.

Jeden z użytkowników Reddita powiązał złośliwe commity w swoich repozytoriach z zainstalowaniem złośliwej wtyczki w Cursor (edytorze kodu opartym na Visual Studio Code i korzystającym z tych samych wtyczek).
Może to sugerować, że konta były przejmowane przy użyciu tokenów wykradzionych przez opisywane przez nas malware GlassWorm. Było ono rozpowszechniane w złośliwych rozszerzeniach do VS Code (oraz jego forków, takich jak właśnie Cursor).
Gdy właściciel przejętego konta posiada wiele repozytoriów z projektami w Pythonie, złośliwe oprogramowanie umieszczane jest w wielu z nich.
Po przejęciu konta programisty rozwijającego dany projekt na GitHub, atakujący wykonuje rebase ostatniego commita dodając do plików malware. Taki commit jest następnie wypychany z użyciem force-push, dzięki czemu zmiany zostają wprowadzone w oryginalnym repozytorium, jednak trudniej jest je od razu dostrzec. Tytuł ostatniego commita i jego autor są zachowane z oryginału, więc na pierwszy rzut oka nie wzbudzają podejrzeń.
Można jednak zauważyć rozbieżności dat – przykładowo w repozytorium amirasaran/django-restful-admin najnowszy (złośliwy) commit pochodzi z 10 marca 2026, jednak stanowi (ponowny) merge pull requestu z listopada 2024.

Wstrzyknięty kod został zaciemniony trzykrotnie. Zakodowano go do postaci base64, skompresowano (zlib) oraz zaszyfrowano (XOR). Nazwy zmiennych to losowe ciągi 15 znaków, ale jedna z nich powtarza się we wszystkich zidentyfikowanych repozytoriach. Możliwe jest więc ich wyszukanie na GitHub.

Po deobfuskacji malware najpierw sprawdza ustawienia języka i strefę czasową. Jeśli wykryje rosyjskie środowisko, nie wykonuje żadnych dalszych działań. Ponadto złośliwy kod zawiera komentarze w języku rosyjskim:
Może to sugerować, że za kampanią stoją atakujący z Rosji lub stwarzający takie pozory.
Zamiast łączyć się z “klasycznym” serwerem C2 (który można na wiele sposobów blokować), malware do przekazywania instrukcji wykorzystuje blockchain Solana. Odpytuje endpointy Solana RPC o transakcje dla zapisanego na stałe (hardcoded) adresu. W kodzie zapisano 9 różnych endpointów:
Czyni to infrastrukturę C2 bardziej odporną na zablokowanie pojedynczego adresu. Wykorzystanie blockchaina powoduje, że atakujący może dowolnie aktualizować URL payloadu poprzez publikację nowej transakcji – a jej usunięcie jest (praktycznie) niemożliwe. Używany w tej kampanii adres portfela Solana jest tym samym adresem, co wskazany przez badaczy z Koi adres używany w ramach kolejnej fali kampanii GlassWorm.
Malware pobiera adres URL z blockchaina. Na urządzeniu użytkownika pobierane i uruchamiane jest także Node.js. Następnie z uzyskanego adresu pobierany jest główny payload (w formie zaszyfrowanej), a w nagłówkach odpowiedzi serwera przesyłany jest klucz do jego odszyfrowania.
Pełna historia instrukcji C2 jest trwale zapisana jako transakcje w Solana. Badaczom udało się je pobrać. Najwcześniejsza transakcja pochodzi z 27 listopada 2025 – ponad trzy miesiące przed pierwszymi przejętymi repozytoriami. Adres ma łącznie 50 transakcji – atakujący regularnie aktualizuje adres URL payloadu. Zdekodowane URL payloadów ujawniają 6 adresów IP serwerów C2.
Każde memo zawiera zakodowany w base64 URL wskazujący na aktualny serwer dostarczający payload. Badacze ustalili adresy, z których korzystano w tej kampanii:
Adresy IP 45.x należą do hostingu Vultr, a 217.69.x to rosyjski zakres.
Choć nie był to atak wycelowany w konkretny projekt, atakującym udało się wdrożyć złośliwy kod do około 200 repozytoriów (część z nich wycofała już wprowadzone zmiany). Szczególnie interesujący jest sposób działania infrastruktury C2 – a ze względu na jego podobieństwa (w tym pokrywający się adres portfela) do kampanii GlassWorm – można przypuszczać, że to po prostu kolejny krok atakujących po wykradzeniu poświadczeń nieświadomych niczego programistów.
Jeśli słuszne są przypuszczenia o wykradaniu tokenów GitHub przez złośliwe wtyczki – główną rekomendacją byłoby ograniczanie ich liczby do niezbędnego minimum. Warto przyjąć taką strategię niezależnie od tego, czy akurat one tutaj “zawiniły”. Polecamy również nasze dotychczasowe teksty o złośliwych wtyczkach.
W kwestii tokenów GitHub, zwracamy uwagę na możliwość szczegółowej kontroli ich uprawnień – warto korzystać z wielu tokenów z minimalnymi koniecznymi uprawnieniami:

Takie rozwiązanie ułatwi też szybkie zablokowanie dostępu i może zmniejszyć szkody w przypadku wykradnięcia/wycieku pojedynczego tokenu. Wrażliwym projektom polecamy skorzystanie z kluczy SSH (najlepiej zabezpieczonych hasłem i przechowywanych na tokenie sprzętowym, np. YubiKey).
Portfel Solana (C2): BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC
Portfel Solana, z którego zamieszczano konfigurację: G2YxRa6wt1qePMwfJzdXZG62ej4qaTC7YURzuh2Lwd3t
Nazwa zmiennej w kodzie: lzcdrtfxyqiplpd
Adresy IP:
~Tymoteusz Jóźwiak
Dzięki za kompleksowe opracowanie – dobra robota!
Podsumowując: force‑push nie jest wektorem ataku, tylko mechanizmem użytym po przejęciu kont. Przy poprawnie wdrożonych branch protections, reviews i audycie zdarzeń GitHuba, nawet taki scenariusz zostawia ślady. Problemem tutaj jest supply chain + credentials hygiene, nie sam workflow DevOps.