W ostatniej łatce Microsoftu służącej do usunięcia wielu podatności bezpieczeństwa znalazła się także między innymi podatność umożliwiająca eskalację uprawnień, którą niedawno znalazł i zgłosił Piotr Madej z zespołu AFINE. Dziś opiszemy, na czym podatność ta polegała i jak można ją było wykorzystać.
Czym jest eskalacja przywilejów i dlaczego to problem?
Eskalacja przywilejów, z angielskiego Elevation of Privileges, to podatność umożliwiająca podniesienie uprawnień użytkownika na systemie operacyjnym. Czyli w skrócie, jeżeli nasz użytkownik na stacji posiada status „konto z ograniczeniami” lub „konto gościa„, to jeżeli mamy taką podatność i ją wykorzystamy, to w efekcie staniemy się administratorem lub SYSTEM’em i będziemy mogli przejąć kontrolę nad całym komputerem, a nie tylko częścią systemu, do której nasze pierwotne ograniczone konto miało uprawnienia. O ile na prywatnych stacjach roboczych czy komputerach domowych zapewne większość z nas korzysta z konta administratora (co jest niezalecane, ale nie oszukujmy się – wygodne), o tyle tego typu podatność w środowisku dużych organizacji, gdzie użytkownik pod żadnym pozorem nie powinien być administratorem, taka podatność może prowadzić do przejęcia kontroli nad całą firmą (jeżeli mamy pecha, a np. inny admin loguje się na naszą stację zostawiając tam tickety kerberosa lub hashe – ale to temat na osobny artykuł).
Szczegóły techniczne podatności – zapinaj pasy i ruszamy!
Podatność znajdowała się w module służącym do zarządzania drukarkami. W windows 10, moduł ten znajduje się w tzw. przystawce konsoli MMC (Snap-In) o nazwie printmanagement.msc, możliwe jest także dotarcie do niego przez funkcjonalność „Printers and scanners” dostępną z menu start.
W powyższym module, na domyślnej (czyli niezmienionej przez nikogo) instalacji Windowsa 10, umożliwiała ona różne, niegroźne działania, w tym operację zarządzania Serwerem Wydruku (Print Server), w tym dodanie nowego „Print Servera”. Poniższy zrzut ekranu pokazuje domyślne ustawienia dla operacji „Manage Server” przed łatką Microsoftu.
Co w tym złego? Na powyższym zrzucie ekranu widzimy, że grupa „Interactive” (czyli każdy zalogowany lokalnie użytkownik) może wykonać operację zarządzaj serwerem, a co za tym idzie, dodać nowy „Print Server„. Aby zrozumieć dlaczego to niedobrze, musimy zrozumieć, na czym polega dodanie Print Server’a od kuchni.
Jedną z metod dodania nowego Print Servera, jest kliknięcie w plik konfiguracji takiego serwera, którego rozszerzenie to .printerexport. Windows rozpoznaje takie pliki domyślnie. Jeżeli taki plik znajdzie się na systemie, a my mając uprawnienia do dodania serwera wydruku (a przed patchem miał je każdy) otworzymy taki plik, to rozpocznie się proces instalacji nowego serwera wydruku. Poniższy zrzut ekranu przedstawia przykładowy plik .printerexport:
Ale co konkretnie jest w tym pliku? Otóż standardowy plik .printerexport jest to tak naprawdę archiwum .zip (podobnie jak pliki MS Office, które też są archiwami), a przykładowy plik tego formatu przestawiamy na poniższym zrzucie ekranu:
W środku zawiera on między innymi definicje sterowników drukarek zawarte w plikach XML oraz biblioteki .DLL, które wspierały działanie tych funkcji. Aby przygotować „złośliwy” plik importu serwera wydruku, należało więc wziąć prawidłowy plik (można go było uzyskać przez funkcjonalność eksportu), i zmodyfikować archiwum tak, żeby zawierało
- Złośliwą bibliotekę .DLL
- Odniesienie do tej biblioteki w pliku .XML
Sama biblioteka była tak naprawdę przerobioną wersją oryginalnego pliku „version.dll” który jest prawidłowym komponentem systemu Windows. Wersja „złośliwa” zawiera wszystkie funkcje pliku windowsowego plus odpalenie cmd.exe czyli tzw. shella 🙂
Więcej o tej technice tworzenia bibliotek DLL możesz przeczytać tutaj.
Poza biblioteką DLL, sam plik .XML również musiał być odpowiednio sformatowany – odniesienia do bibliotek musiały być zakodowane heksadecymalnie:
Poniżej widzimy podświetlony blok w postaci odkodowanej:
Czyli na razie mamy spreparowane archiwum, ale jak odpalić zawartego w naszej bibliotece „shella„?
Nie tak szybko…
Póki co wiemy, że jest funkcjonalność instalacji drukarki z pliku, i że mamy do niej dostęp. Wiemy też, że możemy ten plik spreparować, czyli będzie to nasz punkt wejścia. W jaki sposób jednak ten plik może zostać uruchomiony?
Otóż kiedy import nowego Print Server’a zakończy się, pliki z naszego archiwum .printerexport są kopiowane do lokalizacji C:\Windows\System32\spool\drivers\x64\3\*
Na poniższym zrzucie ekranu widać, że po jednym z importów w wyżej wymienionym folderze znajdują się nowe pliki .DLL, będące bibliotekami do nowo zainstalowanego Print Servera:
Jak to możliwe, że będąc dalej zwykłym użytkownikiem możemy zapisać coś do katalogu systemowego w system32? Otóż zadanie importu jest wykonywane przez usługę Print Spooler (spoolsv.exe) działającą z uprawnieniami SYSTEM. Czyli użytkownik mógł zmusić usługę działającą z wysokimi uprawnieniami do odpalenia jego pliku, co jest świetnym punktem wejścia. Tylko, że… co z tego, że skopiujemy coś do katalogu systemowego, skoro ten plik nie jest nigdy uruchamiany, a jedynie przenoszony?
DLL Sideloading
Czas ostatecznie połączyć wszystkie kropki – otóż jak się okazuje, sama obecność odpowiednio nazwanej biblioteki .DLL w katalogu driverów była wystarczająca do podniesienia swoich uprawnień, ponieważ na systemie istniała jeszcze jedna podatność, którą mało kto chce zazwyczaj naprawiać, bo uważana jest za niegroźną, a mowa tu o tzw. DLL Sideloading (Hijacking).
Jeżeli aplikacja na systemie windows chce wykorzystać jakąś bibliotekę .DLL, a w kodzie tej aplikacji nie podano bezwględnej ścieżki, gdzie konkretnie ta biblioteka się znajduje, to windows pomaga aplikacji znaleźć zagubioną bibliotekę, samemu „podpowiadając” różne lokalizacje z domyślnej listy, między innymi aktualny folder.
I tak, jeżeli aplikacja c:\windows\cośtam.exe potrzebuje do działania biblioteki version.dll, a tej nigdzie nie ma, to Windows w pierwszej kolejności spróbuje załadować ją z lokalizacji c:\windows\version.dll. Podatność taka często nie jest adresowana ponieważ zasadniczo nikt nie powinien mieć prawa do zapisu np. w c:\windows, więc wiele usług podatnych jest na DLL Sideloading/Hijacking, ale nie ma tego jak wykorzystać, ponieważ nie można stworzyć sobie nowej DLL’ki w krytycznych, systemowych lokalizacjach. Problem pojawia się, kiedy komuś jednak uda się zapisać tam jakiś plik, bo wtedy ze zwykłego zapisu biblioteki mamy automatyczne wykonanie kodu…
Tak się składa, że usługa Print Spooler była podatna także na DLL hijacking i podczas startu poszukiwała bezskutecznie pliku version.dll, więc jeżeli nasza złośliwa paczka do instalacji zawierała plik version.dll, to był on kopiowany do folderu systemowego ze sterownikami, gdzie z kolei windows „pomagał” usłudze Print Spooler ten plik znaleźć:
W ten sposób, operacja instalacji nowego Print Server’a prowadziła do zapisu złośliwej biblioteki w lokalizacji, skąd po restarcie systemu ładowała ją usługa systemowa Print Spooler.
Podsumowanie
- Problemem był fakt, że funkcjonalność instalacji Serwera Wydruku (Print Server) była dostępna dla każdego, chociaż wszystko co ona robiła odbywało się w tle z poziomu usługi „Print Spooler”, która była „bardziej uprzywilejowanym” przedłużeniem ręki użytkownika
- Paczkę do importu nowego serwera można było dowolnie zmanipulować, osadzając w niej złośliwe biblioteki .DLL. W tym przypadku, umieszczono w niej plik version.dll, który odpalał „shell’a”
- W trakcie importu, cała zawartość paczki była kopiowana do folderu systemowego w c:\windows\system32\spool\drivers\x64\3*
- Usługa Print Spooler była podatna na DLL Hijacking, i podczas startu ładowała plik version.dll z katalogu c:\windows\system32\spool\drivers\x64\3*, czyli tam, gdzie wypakowaliśmy zawartość naszej złośliwej paczki
- Po restarcie komputera (inaczej użytkownik nie mógł zrestartować usługi) usługa Print Spooler uruchamiała się ponownie, ładując złośliwy version.dll jako NT AUTHORITY/SYSTEM
- „Bonusowa funkcjonalność” spreparowanej biblioteki .DLL powodowała, że po restarcie systemu odpalał się shell (cmd.exe) z uprawnieniami NT AUTHORITY/SYSTEM.
Podatność ta nie należała więc do trywialnych, ponieważ tak naprawdę wymagała połączenia kilku podatności w całość. Za odkrycie podatności Microsoft wypłacił nagrodę w ramach programu Bug Bounty. Znalazcą podatności i twórcą eksploita jest Piotr Madej z zespołu AFINE – serdecznie gratulujemy i dziękujemy za podzielenie się szczegółami technicznymi tego skomplikowanego buga 🙂