Poprzedni wpis w całości poświęcony był obfuskacji, czyli technice, która zapewnia nam wykonanie złośliwego kodu na komputerze ofiary. Biorąc pod uwagę stopień skomplikowania operacji prowadzonych przez grupy APT, sam „code execution” to zdecydowanie za mało. Aby w pełni uświadomić sobie skalę operacji, które są prowadzone w prawdziwych systemach możemy rzucić okiem na matrycę MITRE, która zawiera zestaw technik wykorzystywanych przez adwersarzy na kolejnych etapach działania. W ramach prowadzenia operacji typu Red Teaming działamy w podobny sposób – warto więc zaprzyjaźnić się z matrycą MITRE.
Powyższy obrazek to tylko fragment całej matrycy. Jednak już w oparciu o ten fragment widzimy, iż „Execution” to tylko jeden z wielu elementów, na które składa się TTP (Tactics, Techniques and Procedures) hakerów. Zaraz po umiejętności wykonania kodu w sieci ofiary znajduje się tytułowe „Persistence”. Czemu jest ono takie ważne? Dlaczego pojawia się tak szybko? Jak je uzyskać? O tym będzie ten wpis.
Czym jest tytułowe persistence?
Wśród dosłownych tłumaczeń „persistence” znajdują się takie słowa jak zawziętość, trwałość, uporczywość. W kontekście cyberbezpieczeństwa oznacza to zdolność atakującego do utrzymania się w skompromitowanym systemie, bez potrzeby ponownego przełamywania zabezpieczeń i uzyskiwania initial footholdu. Innymi słowy – są to techniki, które pozwalają nam na stałą obecność w zaatakowanym systemie. Pozwalają chronić się przed restartem stacji roboczej lub usunięciem malware przez oprogramowanie antywirusowe. Persistence rozumiany w szerszym znaczeniu – jako obecność w sieci, pozwala na utrzymanie obecności w ekosystemie choćby przy zastosowaniu działań naprawczych przez Blue Team i Administratorów. choćby o ile stacje robocze i serwery zostaną przywrócone z backupów – persistence może być utrzymany z wykorzystaniem IOT, sprzętu sieciowego, drukarek czy telefonów VOIP. Urządzenia takie jak drukarki są fantastycznym miejscem do ukrycia się – przestarzały software, kiepski monitoring, dostęp do wielu segmentów sieci. W większości przypadków na tego typu urządzeniach znajduje się pełnoprawny OS, zwykle Linux. Podsumowując – persistence można traktować jako zdolność do utrzymania obecności:
- w ramach danego systemu operacyjnego,
- w ramach skompromitowanej sieci informatycznej.
Techniki persistence
Zanim zabierzemy się za praktykę, odpowiedzmy sobie na pytanie „W jaki sposób mogę uzyskać persistence w systemach Windows?” Technik jest kilka, ale wymieńmy sobie kilka podstawowych:
- wpisy w rejestrze Run oraz RunOnce (zarówno dla użytkownika – po zalogowaniu, oraz dla systemu – w momencie uruchomienia);
- Zaplanowane zadania (Scheduled Tasks);
- Złośliwy serwis;
- Junction Folder;
- Programy w Startup;
- RDP Backdoors.
Część z powyższych technik możemy wykonać jako użytkownik nieuprzywilejowany, inne natomiast wymagają podniesienia sobie uprawnień. Powyższe techniki można oczywiście przyporządkować do poszczególnych technik MITRE ATT&CK dla Persistance.
Praktyka, praktyka i jeszcze raz praktyka
Na potrzeby tego wpisu zakładamy, iż udało nam się uzyskać dostęp do komputera ofiary, która pracuje na systemie Windows 10.
Uzyskany w ten sposób dostęp możemy bardzo łatwo utracić – wystarczy, iż użytkownik zrestartuje komputer. Z pomocą przychodzi nam jednak skrypt do Cobalt Strike o nazwie StayKit. Na marginesie – bardzo polecam bloga kitploit.com, masa ciekawych artykułów, mniej i bardziej technicznych. Skrypt StayKit wykorzystuje binarkę SharpStay, którą można pobrać stąd i skompilować. Sam proces kompilacji jest bardzo prosty.
Po skompilowaniu kodu i wrzuceniu pliku binarnego do katalogu z Aggressor Scriptem StayKit.cna możemy załadować skrypt.
Po załadowaniu skryptu, w rozwijanym menu naszego beacona pojawia się dodatkowy element – „Persistence”.
Na powyższych zrzutach ekranu możemy zauważyć, iż skrypt umożliwia nam wykonanie kilku podstawowych technik o których wspominaliśmy wyżej. Podzielone są one również pod względem uprawnień z jakim wykonujemy polecenia na zdalnej stacji. Ponieważ nie mamy póki co podniesionych uprawnień, spróbujmy zapewnić sobie persistence poprzez dodanie skryptu do rejestru UserInitMprLogonScript.
Non-elevated: UserInitMprLogonScript
Po wybraniu odpowiedniej opcji z rozwijanego menu naszego pluginu, musimy uzupełnić kilka ważnych pól.
- Command – polecenie, które ma znaleźć się jako dane wartości „UserInitMprLogonScript” w kluczu Environment.
- Drop Location – miejsce gdzie chcemy umieścić nasz skrypt
- Custom File – nasz złośliwy skrypt.
Po uzupełnienie pól i wcisnięciu przycisku „Execute”, uzyskujemy odpowiednie wpisy w rejestrze oraz przesyłamy plik msupdate.ps1 na komputer ofiary.
Po przeanalizowaniu zmian na zainfekowanym systemie, upewniamy się, iż program zadziałał w prawidłowy sposób. Odpowiedni wpis w rejestrze został utworzony, natomiast skrypt msupdate.ps1 został umieszczony w katalogu C:\Windows\Temp.
Nie pozostaje nam nic innego jak zrestartować stację i sprawdzić czy uzyskamy połączenie.
Jak widać na powyższych screenshotach, udało się uruchomić skrypt. Rzecz jasna powinienem dodać argument „hidden” do programu powershell oraz lepiej zaobfuskować skrypt msupdate.ps1, jednak nie to jest celem tego wpisu.
Elevated: CreateService
Spróbujmy teraz utworzyć stworzyć sobie persistence poprzez stworzenie serwisu, który będzie uruchamiany z każdym uruchomieniem stacji. W ten sposób stworzony serwis uruchamia się niezależnie od tego, jaki użytkownik zaloguje się w systemie. Ponieważ użytkownik „piotr” znajduje się w grupie lokalnych administratorów, możemy w bardzo łatwo sposób podnieść sobie uprawnienia sesji.
Niestety w tym przypadku wszelkie próby wykorzystania narzędzia StayKit triggerowały Windows Defendera. Być może muszę przekompilować projekt lub zmienić nieco mój Malleable C2 profile. Pamiętajmy jednak, iż przez cały czas możemy wykonywać polecenia posiadając aktywny beacon i w ten sposób, „ręcznie” stworzyć sobie persistence. Aby utworzyć sobie nowy serwis wystarczy nam cmdlet „New-Service” i odrobina szczęścia do ominięcia Defendera:
Trzeba nadmienić, iż przy budowie złośliwych plików executable korzystam z loaderów od https://ghttps://github.com/mgeeky/ lub https://github.com/boku7/, które z kolei wykorzystują technikę DLL Reflective Injection. Okej, udało nam się stworzyć serwis, który wskazuje na plik PE o nazwie dcomsvc86.exe. Warto w tym miejscu zaznaczyć, iż najbardziej eleganckim rozwiązaniem byłoby napisanie swojej DLLki, która byłaby umieszczona w kluczu HKLM\SYSTEM\CurrentControlSet\services\[złośliwy serwis]\Parameters, a za obsługę serwisu odpowiadałby svchost.exe. Postaram się przygotować taką dllkę i poświęcić jej oddzielny wpis. Nadszedł czas na weryfikację konfiguracji nowego serwisu i zrestartowanie stacji.
Złośliwy kod został wstrzyknięty do procesu rundll32.exe. Obecność procesu rundll32.exe, bez żadnych argumentów, powinna budzić nasze podejrzenia, ponieważ ten program co do zasady przyjmuje argumenty w postaci nazwy biblioteki i eksportowanych funkcji.
Na koniec jeszcze jedna ciekawostka – Defender z powyższymi zabawami radził sobie ze zmiennym szczęściem, ale totalnie nie dał sobie rady z wygenerowanym serwisowym PE w wersji 32 bitowej. Po otrzymaniu wyżej wymienionego persistence byłem w stanie dowolnie poruszać się po systemie, a choćby „dotykać” tak kluczowych dla OS miejsc jak pliki SAM i SYSTEM.
Podsumowanie
W tym wpisie przedstawiłem dwa, niezwykle proste i „intuicyjne” sposoby na uzyskanie persistence w zdobytym środowisku. Było dość dużo działania typu „script kiddie”, a mało kodowania, ale mam nadzieję, iż w przyszłości się to zmieni. W kolejnym wpisie pokaże na czym polega persistence poprzez Junction (rodzaj miękkiego dowiązania w systemach Windows) oraz eventy WMI. Żeby rozbudzić apetyty – kilka ostatnich screenów z utworzenia persistence dzięki WMI.