Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book

Zarabianie kryptowalut za pomocą Github Actions? Jak wykorzystano atak na łańcuch dostaw do przejęcia biblioteki Python – ultralytics

23 grudnia 2024, 01:53 | W biegu | 0 komentarzy

Ataki na łańcuch dostaw nie są nowością w świecie IT security. Od książkowego Solarwinds, przez legendarny backdoor w SSH,  po ataki na infrastrukturę służącą do publikacji paczek Pythona – ten rodzaj zagrożenia wciąż powinien być traktowany poważnie. Zwłaszcza, że wykorzystywane są coraz bardziej pomysłowe sposoby na przemycenie niechcianego kodu do popularnych projektów. I chociaż tym razem, nie jest to aż tak koronkowa robota, jak w przypadku biblioteki XZ, to trzeba przyznać, że atakujący wykazali się wyjątkową pomysłowością. Przeanalizujmy ciekawy atak na pythonową bibliotekę ultralytics, służącą do działania na obrazach.

TLDR:

  • Ultralytics to otwarta, pythonowa biblioteka implementująca między innymi detekcję obiektów, segmentację i klasyfikację obrazów.
  • Punktem ataku był pipeline CI/CD, w którym atakujący sprytnie ukryli kod, który okazał się być koparką kryptowalut.
  • Osoby odpowiedzialne za utrzymanie projektu w pierwszej chwili źle zlokalizowały miejsce ataku, w rezultacie wydając drugą “poprawioną” wersję, która również zawierała złośliwy kod.

Jak donosi ReverslingLabs, 4 grudnia 2024 doszło do naruszenia i opublikowania wersji biblioteki, oznaczonej numerem 8.3.41, zawierającej koparkę kryptowalut – XMRig. Niestety wydana następnego dnia, wersja 8.3.42 też była zainfekowana, mimo zapewnień o jej bezpieczeństwie i załataniu wpadki. Co ciekawe, w kolejnych dniach wersje 8.3.45 i 8.3.46 opublikowane w PyPI również zawierały złośliwy kod. Tutaj źródła z kolei podają, że incydenty z repozytorium PyPI, były pokłosiem wykradzenia tokenów w pierwszej fali ataków. 

Jak udało się doprowadzić do infekcji tak popularnego pakietu? Zwykle dochodzi do tego w wyniku ataku “od środka” organizacji przez tzw. insider threat – wrogie działania członka zespołu. Takim modelem ataku była postać (najpewniej fikcyjna, a być może pod fałszywą flagą) Jia Tana – programisty, który wprowadził backdoora w testach biblioteki XZ w celu ataku na projekt OpenSSH. Czasami atakujący przejmują konto developera, jak w przypadku dodania malware do popularnej biblioteki web3.js. Jednak w przypadku ultralytics została użyta metoda, pozwalająca na wstrzyknięcie kodu do wykonywanego workflowu Github Actions. Atak polega na tym, że w czasie wykonywania poszczególnych skryptów, wyrażenia oznaczone jako ${{ wyrażenie }} mogą przyjąć wartości, które bez odpowiedniego escapowania oraz filtrowania, mogą trafić do powłoki, która potraktuje je jako element polecenia. Działa to w sposób zbliżony do ataku SSTI, tylko nie wymaga skomplikowanych silników szablonów – wystarczy powłoka systemu. 

O problemie badacz Adnane Khan informował już w sierpniu. Chodzi o fragment kodu definicji action.yml:

Rysunek 1. Fragment issue zgłoszonego przez badacza, opisującego szczegóły problemu

Jak zaznaczono w powyższym issue, wyrażenia w ${{ }} są de facto kontrolowane przez użytkownika i mogą posłużyć do wstrzyknięcia kodu uruchamianego przez dyrektywę run.

Do ataku wykorzystano bardzo aktywne na GitHubie konto:

Rysunek 2. Screenshot pokazujący użytkownika, który dokonał ataku przy pomocy pull-requestów (źródło: wiz)

Użytkownik ten stworzył dwa podejrzane pull requesty. 

Rysunek 3. Pull request otwarty przez użytkownika, z bardzo dziwną nazwą gałęzi (źródło: GitHub)

Wnikliwy czytelnik zauważy, że URL zawiera fragmenty poleceń bashowych, które pobierają plik file.sh, a następnie go wykonują przez wykorzystanie potoku nienazwanego. Ponieważ nazwa gałęzi nie może zawierać spacji, wykorzystana została zmienna środowiskowa ${IFS} – Internal Field Separator, która pozwala powłoce systemowej (w tym przypadku bashowi) dzielić polecenia na tokeny. Pentesterzy znają zapewne tę zmienną, ponieważ to częsty trik pozwalający na obejście filtrowania np. w WAF-ach. 

Skrypt z pliku file.sh niestety nie jest dostępny już do dalszej analizy, ale założyć można, że po prostu dodawał złośliwy kod do projektu. Informację o różnicach w paczkach opublikowanych na GitHubie oraz PyPI wrzucił zaniepokojony użytkownik.

Biorąc pod uwagę, jak popularny i często używany jest projekt, który przestępcy wzięli na warsztat, to atak ten został przeprowadzony w sposób naprawdę przemyślany, chociaż nie wymagał rozbudowanej wiedzy. Wystarczyło zauważyć, że luka, o której zostali poinformowani programiści projektu, została ponownie wprowadzona do kodu. 

Liczba rzeczy, o których należy pamiętać rozwijając dowolny projekt, tak aby nie został on wykorzystany do niecnych celów, stale się wydłuża. Jeśli nie mieliście na niej kontroli wykonania kodu w środowisku CI/CD, to koniecznie należy zapoznać się z dobrymi praktykami DevSecOps i zadbać o to, aby Wasz kod nie został zbackdoorowany na ostatniej prostej do wydania. 

Jeśli chodzi o użytkowników końcowych – cóż, pozostaje śledzić zmiany i weryfikować kod pobranych paczek (a nie zawartości samego repozytorium, bo jak pokazuje doświadczenie, to mogą być – i często są – dwie osobne historie). Dodanie rozwiązań z zakresu SAST/DAST obejmujących kod i jego zależności – nie powinno zaszkodzić. W przypadku minerów problem nie jest “aż” tak poważny, ponieważ łatwiej je wychwycić ze względu na charakterystykę działania (duże zużycie zasobów). Z drugiej strony – to tylko przykład i nieco bardziej zaawansowany atakujący będzie w stanie wykorzystać ten rodzaj ataku na łańcuch dostaw do wyrządzenia większych spustoszeń. 

~fc

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

Odpowiedz