Żądny wiedzy? Wbijaj na Mega Sekurak Hacking Party w maju! -30% z kodem: majearly

Usługi systemowe Windows w kontekście cyberincydentu

20 lutego 2023, 09:48 | Aktualności, Teksty | komentarzy 7

Usługi systemowe systemu Windows są z punktu widzenia atakującego bezcennym mechanizmem. Wynika to z paru niezależnych, dobrze uzupełniających się cech:

  1. Natywnie pracują zdalnie. Cała idea usług, ich API czy narzędzia, od samego początku projektowane były z myślą o zdalnym zarządzaniu.
  2. Automatycznie uruchamiają się wraz ze startem sytemu.
  3. Mają dowolnie wysokie uprawnienia w systemie Windows.
  4. Działają w ukryciu, a narzędzia GUI pokazują tylko niewielką część informacji o ich prawdziwej naturze.

Oczywiście atakujący najpierw musi mieć wysokie uprawnienia, dopiero później może zmieniać konfigurację usług. Zwykły użytkownik jest zazwyczaj ograniczony do ich przeglądania, ewentualnie pytania o aktualny stan. Jednak w przypadku, kiedy system zostanie skutecznie zaatakowany, to właśnie usługi są jednym z najlepszych sposobów zagwarantowania stałej obecności i sytuacja ta nie zmieniła się znacząco od ponad 20 lat.

Od nieco bardziej technicznej strony, usługi systemowe są specjalnymi (ponieważ komunikują się przez Services API) procesami, uruchamianymi i zarządzanymi przez Service Manager – proces o nazwie services.exe, uruchamiany automatycznie na bardzo wczesnym etapie startu systemu. Service Manager wczytuje konfigurację usług z bazy danych przechowywanej w rejestrze (HKLM\System\ CurrentControlSet\Services\), uruchamia procesy potomne zgodnie z zapisanymi w bazie regułami, a następnie komunikuje się z każdym z tych procesów przez funkcję ControlService(), używając specjalnych kodów od 0 do 255. Część z tych kodów jest znana jako Stop, Pause itp., inne są mniej oczywiste, a wszystko powyżej 128 jest pozostawione do dowolnego użycia przez programistę tworzącego daną usługę.

Gdyby w typowym ataku, atakujący chciał sobie właśnie przy pomocy usług systemowych zapewnić stałą obecność, powinien skupić się na kilku istotnych aspektach konfiguracji. Równocześnie, obrońcy, znając cele atakującego mogą zwykle takie usługi próbować wykryć i zablokować. Techniczne aspekty warte zwrócenia uwagi to:

Nazwa usługi. Zazwyczaj nazwa jest pierwszą rzeczą, którą widzi administrator. Z oczywistych powodów, celem atakującego jest takie jej dobranie, żeby nie wzbudziła podejrzeń. Dlatego złośliwe usługi raczej nie mają nazw generowanych losowo, ani zachęcających do pogrzebania głębiej. Dobrze dobrana nazwa może odnosić się do wnętrzności systemu operacyjnego, sugerując obrońcom „nie dotykaj, po prostu szukaj dalej”. Coś typu PnP Enumerator, Transport Layer Security Helper, itp. Im bardziej nieoczywiste będą wyniki wyszukiwania w Google, tym lepiej. Dodatkowo, atakujący powinni pamiętać, że każda usługa ma tak naprawdę dwie nazwy: Display Name (nazwę wyświetlaną) i Service Name (nazwę w bazie danych). Obie nazwy można zobaczyć we właściwościach usługi w konsoli services.msc i w wielu innych miejscach. Dla obrońców, sama nazwa w zasadzie jest bezużyteczna. Może być celowo myląca, albo po prostu wykorzystywać nazwę oryginalnej usługi, którą atakujący usunął i zastąpił złośliwą. Oczywiście, i tak warto sprawdzić czy atakujący nie był niemądry albo nieostrożny. Obrońca może wyświetlić listę wszystkich usług (tak lokalnie, jak i zdalnie) przy pomocy PowerShella i WMI: gwmi Win32_Service | select Name, Displayname (rysunek 1).

Rys. 1. Wynik polecenia gwmi Win32_Service listujący nazwę i nazwę wyświetlaną usługi

Opis usługi. Atrybut, który widoczny jest w GUI, za to dużo trudniej do niego sięgnąć przy pomocy aplikacji i skryptów. Wynika to z faktu, że ten atrybut został dodany do Services API stosunkowo późno – dopiero w Windows 2000. W efekcie, stworzenie nowej, w pełni funkcjonalnej usługi nie wymaga ustawienia żadnego opisu. Obrońcy mogą przeprowadzić prosty test: uruchomić services.msc i posortować po kolumnie „Description” (albo gwmi win32_service | where-object {$_.description -eq $null}) i niemal natychmiast zidentyfikować usługi bez opisu (rysunek 2). To one w pierwszej kolejności powinny zostać poddane analizie jako nietypowe. Oczywiście istnieją usługi nie mające opisu i nie robiące nic złego (parę ciepłych słów o ich twórcach), tak samo jak i malware, który ma piękny opis. Stwierdzić jednak można, że mimo braku stuprocentowego zaufania do opisów, i tak warto ich użyć do identyfikacji podejrzanych usług. Atakujących pocieszyć może natomiast fakt, że jeżeli planują ustawiać jakiś opis, to prawdopodobnie i tak nigdy nikt go nie przeczyta.

Rys. 2. Identyfikacja usług bez opisu

Pliki wykonywalne. Teoretycznie, administrator powinien znać każdy plik wykonywalny w swoim środowisku. Bez wymówek, zwłaszcza że PowerShell może pomóc to zautomatyzować. Oczywiście pliki wykonywalne wypada poznać przed atakiem, żeby później móc łatwo odróżnić oryginały od malware. Atakujący wiedzą oczywiście, że to się w praktyce nie zdarza często, a gdy już się zdarzy, administrator prawdopodobnie skupi się na plikach *.exe, pozostawiając *.dll na później, mimo że z punktu widzenia kodu wykonywalnego, różnica między nimi niemal nie istnieje. DLL niestety są trudniejsze do opanowania, gorzej opisane, jest ich więcej, powtarzają się i częściej zmieniają. Nawet jeżeli jakiś administrator podjął próbę zebrania informacji o wszystkich *.dll, z niezłym prawdopodobieństwem założyć można, że taka informacja dawno jest nieaktualna. I tu pojawiają się na scenie supermoce usług systemowych: równie sprawnie działają w oparciu o pliki *.exe, jak i o pliki *.dll. Co więcej, sam system Windows uruchamia większość swoich wbudowanych usług właśnie w oparciu o DLL. Service Manager uruchamia specjalny proces svchost.exe a on dopiero ładuje DLL wskazaną w rejestrze i uruchamia jej kod. W efekcie, atakujący używający DLL po to, żeby upodobnić się do natywnych usług systemu i po to, żeby uniknąć wykrycia przez tych, którzy nie do końca wiedzą jak DLL monitorować. Administrator widząc usługę opartą o svchost.exe pomyśli najczęściej „a to coś z systemu” i na tym zakończy się cała analiza, tym bardziej, że ogromna część narzędzi diagnostycznych i monitorujących skupia się na poziomie procesów i plików *.exe, a nie ładowanych z plików *.dll bibliotek. Jedyną nadzieją dla obrońców jest badanie DLL odpowiedzialnych za usługi równie dokładnie, jak badanie takie wykonują dla EXE. Skrypt PowerShell pomoże to zrobić sprawnie i bez wysiłku.

Konto i przywileje usług. Każdy proces, a więc i każda usługa systemowa ma swoją tożsamość (kontekst) w systemie. Jeżeli nikt nie powie jaki to ma być kontekst, to jest on dziedziczony od procesu rodzica, czyli services.exe działającego jako LocalSystem. W efekcie, większość usług systemowych działa z najwyższymi przywilejami jakie spotkać można w systemie. Jeżeli atakujący zamierza pozostać niewykryty, pozostawia domyślną tożsamość bez zmian. Niczym się wtedy nie wyróżnia a równocześnie ma super moce. Niezależnie od systemowych tożsamości, usługi systemowe mogą zostać skonfigurowane tak, aby działały na regularnych (lokalnych lub domenowych) kontach. Choć jest to dość rzadkie w scenariuszach związanych z atakami, to należy zdawać sobie sprawę, że konfiguracja taka nie dość, że wymaga znajomości hasła konta w czasie konfiguracji usługi, to jeszcze umożliwia przeczytanie tego hasła przez każdego użytkownika o lokalnych prawach administratora. Wykorzystywana w tym celu jest impersonacja do LocalSystem i zwrócenie się do LSASS o zawartość sekretu powierzonego wcześniej przez Service Manager.

Aktywność usługi. Z punktu widzenia atakującego, celem jest działanie usługi umożliwiającej wykonanie założonych zadań z wysokimi uprawnieniami. Najczęściej będzie to potrzebne tylko sporadycznie, w szczególnych momentach ataków. Pomiędzy aktywnościami, wykorzystywana przez atakującego usługa powinna być tak niezauważalna, jak to tylko możliwe. Dlatego, dopóki nie jest to naprawdę niezbędne, usługa taka nie powinna otwierać portów, łączyć się z internetem, sięgać do plików czy rejestru. Obrońcy wyłapią taką aktywność bardzo szybko i najprawdopodobniej w jakiś sposób ograniczą atak. Ideałem byłoby stworzenie usługi działającej w pełni synchronicznie, nie podejmujące żadnego działania, dopóki nie dostaną sygnału, jednak oznaczałoby to, że muszą na taki sygnał w jakiś sposób oczekiwać, co też jest widoczne i to w stały sposób. Istnieją mało widoczne dla administratorów sposoby przesyłania komunikatów w Windows (na przykład ETW czy WNF) jednak są zwykle na tyle skomplikowane, że ich użycie jest mało praktyczne. W praktyce prostym, trudnym do wykrycia sposobem może być synchroniczne (co zadany, być może nieregularny, czas) czytanie z miejsca, które nie wydaje się podejrzane i poszukiwanie w nim określonej, najlepiej zmiennej w czasie, zawartości. Przykładowo, usługa może raz na kilka godzin czytać zawartość roota dysku C:. Jeżeli wystąpi tam folder o nazwie MalwareYYMMDD, podjęte zostaną jakieś dalsze działania. Podejście takie jest lepsze niż sprawdzanie istnienia samego folderu, ponieważ próby sięgnięcia do nieistniejącego folderu są łatwe do wykrycia (czas, inicjujący proces, fakt, że są podjęte, nazwa folderu itp.), podczas gdy czytanie całego folderu nadrzędnego i samodzielne sprawdzenie co jest jego zawartością zostawia o wiele mniej śladów. Warto również pomyśleć nad tym, żeby aktywność była wstrzymywana, jeżeli ktoś aktywnie pracuje na komputerze. Akcje podejmowane tylko po zablokowaniu konsoli czy włączeniu wygaszacza, w oczywisty sposób będą trudniejsze do zauważenia.

Komunikacja z atakującym. Cała idea Services API pomyślana jest tak, żeby można było się komunikować z usługami bezczynnie czekającymi na nadejście polecenia. W praktyce, choć jest to kuszący scenariusz, możliwości API trochę przeszkadzają w jego wykorzystaniu, ponieważ realnie możliwe jest przesłanie 7 bitów na raz, a dodatkowo wypadałoby albo mieć już w systemie wysokie uprawnienia (więc po co je zdobywać), albo ustawić usługę tak, żeby przyjmowała komunikaty od użytkowników ze standardowymi uprawnieniami, co z kolei może dać się łatwo zauważyć. Można też czekać na pojawienie się plików lub wpisów w rejestrze w sposób opisany powyżej i korzystanie z danych, które są przekazywane w ten sposób. To, na co warto zwrócić uwagę, to pewna elastyczność. Usługa powinna mieć możliwość wykonania dowolnej akcji zleconej przez atakującego, zamiast polegać na kilku predefiniowanych, zaszytych w kodzie sposobach ataku i/lub dostępu. Pozwoli to w praktyce na „zlecenie” usłudze dowolnych działań, bez jej wymiany na ulepszoną, umiejącą więcej wersję. W wielu scenariuszach może to być bezcenne.

Samoobrona. Kiedy administrator systemu zobaczy jakieś nietypowe lub złośliwe działania, może zacząć aktywnie „walczyć” z podejrzaną usługą. Z drugiej strony – usługa działająca na wysokich uprawnieniach może się bronić. Dwie proste metody obrony (zwłaszcza używane łącznie) polegać mogą na uniemożliwieniu zatrzymania usługi (legalne i przewidziane w API zameldowanie Service Managerowi, że usługa nie może być zatrzymywana) oraz na sprowokowaniu poważnej awarii (na przykład BSOD) w sytuacji, gdy zabity zostanie proces usługi. Teoretycznie możliwe są jeszcze działania oparte o mechanizm procesów chronionych, jednak w praktyce wymagają one specjalnych (zawierających EKU 1.3.6.1.4.1.311.10.3.22) certyfikatów do podpisywania kodu, w praktyce niezdobywalnych dla twórców złośliwych usług. Poza obroną pojedynczej usługi, w grę wchodzą jeszcze rozwiązania bazujące na parze usług obserwujących i naprawiających się wzajemnie. Rozwiązanie takie jest jednak łatwiejsze do zauważenia przez administratora niż jedna usługa, a równocześnie przewaga jest tylko krótkotrwała – świadomy administrator, po paru chwilach zdziwienia, poradzi sobie z dwiema usługami równie skutecznie jak z jedną.

Na koniec, warto zadać sobie pytanie „kto wygra?”. Generalnie, jeżeli usługę udało się zainstalować to już wygrał atakujący. Czy da się to wykryć, czy da się usunąć – można się zastanawiać, ale to już niewielkie pocieszenie. Świadomy administrator powinien wykryć najbardziej typowe techniki, ale tak naprawdę to niewielkie pocieszenie. Podobnie jak w innych przypadkach, dużo lepiej skupić się na skutecznej obronie, niż na walce z atakującym na już przejętym środowisku.

[UWAGA!] Jeżeli jesteś zainteresowany tematyką bezpieczeństwa Windows to zapraszamy na nasze bezpłatne szkolenie (choć zachęcamy do dowolnego wsparcia, które pozwoli nam organizować więcej tego typu wydarzeń): Poznaj bezpieczeństwo Windows. Część pierwsza: usługi systemowe. Wydarzenie odbędzie się on-line 20 marca 2023 roku o godzinie 20:00. Prowadzi Grzegorz Tworek. Zapisać się można tutaj: https://sklep.securitum.pl/poznaj-bezpieczenstwo-windows-1-uslugi-systemowe

~Grzegorz Tworek

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



Komentarze

  1. nazwisko

    Dobry artykuł.

    Odpowiedz
  2. Adam

    Wspaniały artykuł, proszę o więcej.

    Odpowiedz
    • Zapraszamy na (bezpłatne) szkolenie w temacie – link w txt ;-)

      Odpowiedz
  3. Szymops

    Fajny artykuł podeśle go moim kolegom opom

    Odpowiedz
  4. wk

    Jako stary admin, pracujący często z Windows, mogę z całą odpowiedzialnością powiedzieć, że ten artykuł i inne artykuły i wykłady Grzegorza Tworka są w tym temacie ogromnie wnikliwe i pomocne. I tak, zapisałem się już na szkolenie z usług systemowych. Pozdrawiam.

    Odpowiedz
  5. jendrzej

    dobry artykul mordo

    Odpowiedz
  6. Kuba

    Super artykuły, tak trzymać:)

    Odpowiedz

Odpowiedz