W
biologii symbiont to organizm żyjący w symbiozie z innym organizmem (np. bakterie w jelicie grubym u człowieka, bakterie; które trawią celulozę u przeżuwaczy). Symbioza może być obustronnie korzystna dla obu organizmów, ale czasami może być pasożytnicza, gdy jeden organizm zyskuje, a drugi jest uszkadzany. Kilka miesięcy temu zespoły bezpieczeństwa z firmy Intezer oraz BlackBerry odkryły nowe, dobrze maskujące się złośliwe oprogramowanie dla systemu Linux, które działa właśnie w taki pasożytniczy sposób. Tym, co odróżnia Symbiote od innych złośliwych programów dla systemu Linux, z którymi zwykle można się spotkać, jest fakt, iż musi zainfekować inne uruchomione procesy, aby wyrządzić szkody zainfekowanym maszynom. Nie jest to samodzielny plik wykonywalny uruchamiany w celu zainfekowania systemu, ale biblioteka obiektów współdzielonych (.so), która jest ładowana do wszystkich uruchomionych procesów przy użyciu LD_PRELOAD (T1574.006) i pasożytniczo infekuje maszynę. Po zainfekowaniu wszystkich uruchomionych procesów zapewnia aktorowi funkcjonalność rootkita, możliwość zbierania poświadczeń oraz zdalny dostęp.
Najwcześniejsze próbki tego malware pochodzą z listopada 2021 roku i jak zauważają badacze – wydaje się, iż zostało napisane z myślą o sektorze finansowym w Ameryce Łacińskiej (wykorzystywane nazwy domen podszywały się pod niektóre duże brazylijskie banki). Po zainfekowaniu maszyny program ukrywa siebie oraz programy pomocnicze wykorzystywane przez aktora, co sprawia, iż infekcje są trudne do wykrycia. Przeprowadzenie powierzchownej analizy śledczej na zainfekowanej maszynie może nie przynieść żadnych rezultatów, ponieważ wszystkie pliki, procesy i artefakty sieciowe są ukrywane.
Backdoor z kanałem zapasowym i zbieraniem danych:
Oprócz funkcji rootkita udostępniony jest backdoor, który umożliwia operatorowi zalogowanie się jako dowolny użytkownik na maszynie dzięki wcześniej zakodowanego na sztywno hasła i wykonywanie poleceń z najwyższymi uprawnieniami. Taki zdalny dostęp do zainfekowanego hosta uzyskiwany jest poprzez podpięcie się do kilku funkcji PAM (ang. Linux Pluggable Authentication Module). Gdy usługa próbuje użyć PAM do uwierzytelniania użytkownika, złośliwe oprogramowanie sprawdza, czy podane hasło jest zgodne z zakodowanym hasłem w kodzie. jeżeli podane hasło jest zgodne, przechwycona funkcja zwraca odpowiedź powodzenia. Ponieważ podpięcie znajduje się na poziomie PAM, umożliwia to aktorowi uwierzytelnianie się do maszyny dzięki dowolnej usługi wykorzystującej te moduły – w tym Secure Shell (SSH). jeżeli wpisane hasło nie odpowiada temu, zakodowanemu uruchamiana jest funkcja keyloggingu, która je zapisuje i eksfiltruje (szczegóły w dalszej części). Dodatkowo przez kanał DNS (rekordy TXT) jest prowadzona zapasowa komunikacja do swojej domeny dowodzenia i kontroli (C&C / C2). Rekord TXT ma format: %ID_MASZYNY%.%DOMENA_C2%. jeżeli program otrzyma odpowiedź dekoduje jego zawartość BASE64 i sprawdza, czy została ona podpisana poprawnym kluczem prywatnym ed25519, odszyfrowuje zawartość dzięki RC4 i wykonuje skrypt powłoki w wywołanym procesie bash. Ten cały proces w komunikacji DNS może działać jako metoda umożliwiająca odzyskanie dostępu do maszyny w przypadku, gdy normalny proces z usługami korzystającymi z PAM przestanie działać. Po poprawnym zalogowaniu się operatora na zainfekowanej maszynie zapewniana jest funkcjonalność umożliwiająca zyskanie uprawnień administratora (root). Gdy biblioteka współdzielona jest ładowana po raz pierwszy sprawdza zmienną środowiskową: HTTP_SETTHIS. jeżeli zmienna ta jest ustawiona i posiada zawartość to Symbiote zmienia efektywny identyfikator użytkownika i grupy aktora na root, a następnie czyści zmienną przed wykonaniem zawartości dzięki polecenia systemowego. Proces ten wymaga, aby biblioteka miała ustawiona flagę SETUID. Po zakończeniu polecenia systemowego Symbiote również zamyka swój proces, aby uniemożliwić wykonanie oryginalnego procesu. Pozwala to na wywołanie powłoki administratora przez uruchomienie:
HTTP_SETTHIS="/bin/bash -p" /bin/truejako dowolny użytkownik w powłoce. Zbieranie danych uwierzytelniających odbywa się również poprzez podpięcie się do funkcji read libc. jeżeli proces polecenia ssh lub scp wywoła tę funkcję nastąpi przechwycenie danych uwierzytelniających. Są one najpierw szyfrowane algorytmem RC4 przy użyciu wbudowanego klucza, a następnie zapisywane do pliku. Na przykład, jedna z wersji tego złośliwego systemu zapisuje przechwycone dane do pliku /usr/include/certbot.h (IoC). Jak zostało wspomniane wcześniej oprócz przechowywania danych uwierzytelniających lokalnie, dane te są eksfiltrowane sieciowo do C2. Na początku są kodowane szesnastkowo i dzielone na fragmenty, aby je wyprowadzić dzięki żądań DNS (rekordy A) mających format:
%NUMER_PAKIETU%.%ID_MASZYNY%.%ZAKODOWANY_ŁADUNEK_W_HEX%.%DOMENA_C2%Na przykład:
0018008969ce660021636f6d6d616e64202862756666616c6f2900.git.bancodobrasil.dev = if!command (buffalo)Co interesujące Symbiote sprawdza, czy host posiada skonfigurowane serwery rekursywne w /etc/resolv.conf. jeżeli nie, to wykorzystuje serwery DNS firmy Google (8.8.8.8).
Ukrywanie aktywności sieciowej:
Jednym z interesujących aspektów technicznych Symbiote jest jego funkcjonalność podpinania się do Berkeley Packet Filter (BPF). Nie jest on pierwszym złośliwym oprogramowaniem dla Linuksa, które używa eBPF – możemy mówić już raczej o trendzie wykorzystania tego oprogramowania. Gdy administrator uruchamia dowolne narzędzie do przechwytywania pakietów na zainfekowanej maszynie, kod bajtowy eBPF jest w wstrzykiwany do jądra, określając w ten sposób, które pakiety powinny zostać przechwycone. Czyli malware ten najpierw dodaje swój kod bajtowy, aby mógł odfiltrować ruch sieciowy, którego nie chce, aby widziało oprogramowanie przechwytujące pakiety. Dzieje się to poprzez podpięcie się do funkcji setsocktopt libc. o ile funkcja ta zostanie wywołana z opcją SO_ATTACH_FILTER, która służy do filtrowania pakietów na gnieździe sieciowym, to przed kodem BPF dostarczonym przez wywołującą aplikację Symbiote umieszcza swój własny bajtkod. Poniżej znajduje się jedna z wersji bajtkodu wstrzyknięta przez jedną z próbek – zrzuca ona pakiety, jeżeli spełnione są następujące warunki:
- adres IPv6 (protokół TCP lub SCTP) i port źródłowy: 43253 lub 43753 lub 63424 lub 26424
- adres IPv6 (protokół TCP lub SCTP) i port docelowy: 43253
- adres IPv4 (protokół TCP lub SCTP) i port źródłowy: 43253 lub 43753 lub 63424 lub 26424
- adres IPv4 (protokół TCP lub SCTP) i port docelowy: 43253 lub 43753 lub 63424 lub 26424
Chociaż ten bajtkod usuwa pakiety tylko na podstawie numerów portów, to badacze zaobserwowali również filtrowanie ruchu na podstawie określonych adresów IPv4. We wszystkich przypadkach filtrowanie dotyczy zarówno ruchu przychodzącego, jak i wychodzącego z maszyny, co pozwala ukryć oba kierunki komunikacji sieciowej. jeżeli warunek nie jest spełniony, następuje przeskok do początku kodu bajtowego dostarczonego przez aplikację wywołującą filtrowanie. Sposób w jaki ten bajtkod został napisany (zakłada on, iż po nim istnieje jeszcze inny bajtkod oraz przeskakiwanie na początek bajtkodu dostarczonego przez proces wywołujący) sugeruje, iż to złośliwe oprogramowanie zostało napisane przez doświadczonego programistę. Innymi funkcjami ukrywania aktywności sieciowej jest podpięcie się pod wywołania fopen i fopen64. jeżeli jakaś aplikacja próbuje otworzyć /proc/net/tcp to malware tworzy plik tymczasowy i kopiuje do niego pierwszą linię z /proc/net/tcp. Następnie skanuje tą ścieżką linia po linii pod kątem obecności określonych portów. o ile w skanowanej linii znajdzie poszukiwany port, przechodzi do następnej linii. W przeciwnym razie linia ta jest zapisywana do wcześniej stworzonego pliku tymczasowego. Gdy oryginalny plik z tcp zostanie już całkowicie przetworzony Symbiote zamyka go i zwraca deskryptor pliku tymczasowego do aplikacji. Dzięki temu proces wywołujący otrzymuje wynik oczyszczony z wpisów dotyczących połączeń sieciowych, które złośliwe oprogramowanie chce ukryć. jeżeli chodzi o ruch UDP to wykorzystana jest tutaj biblioteka libpcap (pcap_loop). Dzięki niej następuje filtrowanie nazw domen, które Symbiote ma na swojej liście. Każdy odebrany pakiet UDP sprawdzany jest pod kątem występowania łańcuchów domen, które chce odfiltrować. jeżeli znajdzie pasujący fragment ignoruje pakiet i zwiększa licznik. Licznik ten (pcap_stats) wykorzystywany jest do „skorygowania” liczby przetworzonych pakietów poprzez odjęcie wartości licznika od rzeczywistej liczby przetworzonych pakietów. jeżeli ładunek pakietu nie zawiera żadnego z łańcucha tekstowego, który jest na liście wywoływana jest oryginalna funkcja. Także, jak widzimy mamy trzy metody do filtrowania pakietów, aby złośliwe oprogramowanie mogło ukryć swoją aktywność sieciową.
Procesy i narzędzia wspomagające:
Symbiote oprócz ukrywania swojej aktywności sieciowej dba również o siebie i inne pliki wspomagające jego działanie i rozprzestrzenianie. Wewnątrz kodu binarnego znajduje się lista plików zaszyfrowanych również algorytmem RC4. Podobnie jak w ukrywaniu portów – po wywołaniu przechwyconych funkcji złośliwe oprogramowanie najpierw dynamicznie ładuje bibliotekę libc i wywołuje oryginalną funkcję. jeżeli aplikacja próbuje uzyskać dostęp do pliku lub folderu w katalogu /proc malware przegląda dane wyjściowe z nazwami procesów i szuka tych, które znajdują się na jego liście, aby je wykluczyć. Nazwy procesów, które podlegają ukryciu, a zostały wyodrębnione z odkrytych próbek to:
- certbotx64
- certbotx86
- javautils
- javaserverx64
- javaclientex64
- javanodex86
Jeśli jakiś program nie próbuje uzyskać dostępu do czegoś w pseudo systemie plików /proc to malware wyklucza wpisy z listy plików. Pliki wyodrębnione ze wszystkich zbadanych próbek są na poniższej liście. Niektóre nazwy plików odpowiadają nazwom używanym przez Symbiote, podczas gdy inne są zgodne z nazwami plików, co do których istnieje podejrzenie, iż są narzędziami wykorzystywanymi już przez aktora na zainfekowanej maszynie:
- apache2start
- apache2stop
- profiles.php
- 404erro.php
- liblinux.so
- java.h
- open.h
- mpt86.h
- sqlsearch.php
- indexq.php
- mt64.so
- certbot.h
- cert.h
- search.so
Jedną z konsekwencji ładowania Symbiote do różnych procesów za pośrednictwem LD_PRELOAD jest to, iż narzędzia takie jak ldd, które wypisuje biblioteki współdzielone wymagane przez każdy program, będą również listować złośliwe oprogramowanie jako zładowany obiekt. Aby temu zapobiec, malware podpina się pod execve i szuka wywołań tej funkcji ze zmienną środowiskową LD_TRACE_LOADED_OBJECTS ustawioną na 1. Aby zrozumieć dlaczego akurat tak, warto zajrzeć na stronę podręcznika manualnego ldd:
In the usual case, ldd invokes the standard dynamic linker (see ld.so(8)) with the LD_TRACE_LOADED_OBJECTS environment variable set to 1. This causes the dynamic linker to inspect the program’s dynamic dependencies, and find (according to the rules described in ld.so(8)) and load the objects that satisfy those dependencies. For each dependency, ldd displays the location of the matching object and the (hexadecimal) address at which it is loaded. (The linux-vdso and ld-linux shared dependencies are special; see vdso(7) and ld.so(8).)
Gdy Symbiote wykryje takie wywołanie, wykonuje program ładujący tak samo jak ldd, ale z wyniku „wydrapuje” swój własny wpis. Ze względu na swoje mechanizmy ukrywania swojej aktywności infekcja Symbiote może często „przelecieć pod radarem”, szczególnie na systemach, nad którymi nie są rozpięte dodatkowe systemy detekcji. Poza tym badacze nie znaleźli wystarczających dowodów, aby określić, czy ten rodzaj malware jest używany w wysoce ukierunkowanych lub na szeroką skalę atakach.
Więcej informacji: Symbiote Deep-Dive: Analysis of a New, Nearly-Impossible-to-Detect Linux Threat