W dzisiejszym artykule wyjaśnimy i pokażemy, w jaki sposób można wykorzystać błędy w Windows, aby można obejść białą listę blokowanych aplikacji i zabezpieczenia uruchomienia złośliwego kodu Windows. Błędy dotyczą wbudowanej funkcji .Net Core Garbage Collector oraz błędu parsowania ścieżki do podkatalogów w systemie.
Jako przykład stworzyliśmy kod złośliwiej biblioteki DLL i uruchomiliśmy ją na najnowszej wersji Windows 10 (kompilacja numer 2004).

Exploita związanego z błędem parsowania ścieżek do podkatalogów w Windows opisywaliśmy w naszym poprzednim artykule tutaj, w którym pokazaliśmy, jak za pomocą wbudowanych poleceń i ich przełączników Windows możemy uruchomić złośliwy kod. Więcej o technice ukrywania uruchomienia kodu tzw. Living off the Land (LotL) pisaliśmy tutaj.

Zanim przejdziemy do praktyki najpierw przedstawimy trochę teorii. Jeśli znane Ci jest środowisko .Net Core oraz funkcjonalność Garbage Collector’a możesz od razu przejść do sekcji ze scenariuszem.


Platforma .Net Core

.NET Core to platforma oprogramowania typu open source oparta na .Net Standard, która została wydana po raz pierwszy w 2016 roku. W przeciwieństwie do .NET Framework, .NET Core jest wieloplatformowy i dlatego może być wykorzystywany do tworzenia i wdrażania aplikacji napisanych w C # lub F # w systemach operacyjnych Windows, Linux i MacOS. Więcej informacji na temat samej technologii można znaleźć w oficjalnej dokumentacji Microsoft .NET Core.


Co to jest Garbage Collector?

GC .NET, jak każdy GarbageCollector z innych języków programowania, jest odpowiedzialny za przydzielanie i zwalnianie pamięci używanej przez aplikację w czasie jej wykonywania. GC pilnuje (utrzymuje porządek), aby wirtualna prywatna pamięć procesu aplikacji została zwalniana, w przypadku, kiedy nie jest już przez nią wykorzystywana.

Platforma .NET Core umożliwia korzystanie z niestandardowego GC za pośrednictwem zmiennej środowiskowej COMPlus_GCName. Niestandardowy GC ma postać niezarządzanej biblioteki C ++ Dynamic-Link Library (DLL). Domyślna ścieżka instalacji .NET Core w standardowym systemie operacyjnym Windows to „C:\Program Files\dotnet\shared\”. Jak pokazano poniżej, ścieżka jest zapisywalna tylko dla lokalnych administratorów.


W czym tkwi błąd?

Autorem odkrytego błędu jest Paul Laine. Dokładny opis znajduje się tutaj (https://www.contextis.com/us/blog/bring-your-own-.net-core-garbage-collector_. Ideą techniki odkrytej przez Paula jest to, że nisko uprzywilejowany użytkownik może określić niestandardowy Garbage Collector (GC), z którego powinna korzystać aplikacja .NET.
Niestandardowy kod GC można określić, ustawiając zmienną środowiskową powłoki poleceń COMPLUS_GCName, która wskazuje na złośliwą bibliotekę DLL reprezentującą niestandardowy moduł czyszczenia pamięci.

Ponieważ określenie niestandardowej biblioteki dla GC wymaga uprawnień administratora systemu (wymagane uprawnienia do podkatalogów C:\Program Files\dotnet\shared\”). , autor błędu odkrył, że jeśli zdefiniujemy niestandardową ścieżkę w COMPLUS_GCName, podczas uruchomienia aplika GC nie sprawdza jej składni (nie normalizuje i nie sprawdza).
Trik z podaniem jej w postaci „..\..\..\Temp\DLL\biblioteka.dll” pozwala każdemu nieuprzywilejowanemu użytkownikowi na określenie niestandardowego GC do załadowania z dowolnej lokalizacji, w której mogą umieścić swoją bibliotekę DLL.

Warunkiem koniecznym, aby technika mogła zadziałać to biblioteka DLL Gargage Collector’a musi wyeksportować metodę GC_VersionInfo. Wówczas złośliwy kod, który będzie umieszczony w jej metodzie zostanie wykonany po uruchomieniu programu w .NET.


Scenariusz ominięcia zabezpieczeń Windows oraz uruchomienia złośliwego kodu

W naszym scenariuszu pokażemy, jak uruchomić złośliwy kod z napisanej do tego celu biblioteki DLL rozszerzającej standardowy moduł czyszczący (GarbageCollector). Następnie w zmiennej środowiskowej COMPLUS_GCName wskażemy ścieżkę do naszej biblioteki (wykorzystując błąd parsowania ścieżek Windows) i uruchomimy ją za pomocą wbudowanej w Windows komendy „dotnet.exe” z przełącznikiem „h”.
W celu pomyślnego wykonania poniższego scenariusza system operacyjny musi mieć zainstalowane środowisko .Net Core


Krok 1. Utworzenie złośliwej biblioteki DLL

W tym kroku utworzymy bibliotekę DLL w C++ reprezentującą niestandardowy moduł czyszczący. W kodzie musimy wyeksportować funkcję GC_VersionInfo,

a następnie uruchomić w niej złośliwy kod. W naszym przypadku ograniczyliśmy się do uruchomienia prostego komunikatu w postaci pojawiającego się okna MessageBox.
Poniżej prezentujemy wycinek kodu biblioteki GDDLL.dll uruchamiającej prosty komunikat dla użytkownika.


Krok 2. Modyfikacja zmiennej środowiskowej COMPLUS_GCName

Po skompilowaniu biblioteki DLL możemy ustawić zmienną środowiskową COMPLUS_GCName w naszej powłoce „cmd.exe” i skierować ją na skompilowaną bibliotekę DLL:

set COMPLUS_GCName=..\..\..\..\..\..\..\Temp\Projects\GC_DLL\x64\Debug\GCDLL.dll


Krok 3. Wykonanie kodu biblioteki

W celu wykonania kodu w .Net i uruchomieniu naszej biblioteki rozszerzającej GarbageCollector ze złośliwym kodem, musimy wykonać w systemie poniższe polecenie:

dotnet.exe -h

Możemy uruchomić naszą bibliotekę GCDLL.DLL w pojedynczym kroku ustawiając bezpośrednio zmienną COMPLUS_GCName oraz uruchamiając po niej „dotnet.exe” w poniższy sposób

set COMPLUS_GCName=..\..\..\..\..\..\..\Temp\Projects\GC_DLL\x64\Debug\GCDLL.dll & dotnet.exe -h


Jak sobie poradzić z problemem?

Przede wszystkim powodzenie przeprowadzenia tej metody ataku jest możliwe wówczas, gdy w systemie jest zainstalowana platforma .NET Core. Powinniśmy zwrócić uwagę na takie środowiska/ systemy jak:

  • Serwery aplikacyjne
  • Komputery z zainstalowanym środowiskiem programistycznym

Możliwość korzystania z niestandardowego GC jest uzasadnioną funkcją i prawdopodobnie nie powinna zostać usunięta. To na co należy zwrócić uwagę, to czy w jej zmiennej środowiskowej COMPLUS_GCName nie znajdują się „dziwnie” wyglądające ścieżki do plików dll, w szczególności takie, które zawierają znaki ukośnika z przodu i z tyłu oraz dwie kropki pomiędzy„\..\”.
Ponadto zalecane jest monitorowanie procesów, które ładują biblioteki dll z niestandardowych lokalizacji.
Autor wspomnianego powyżej problemu zgłosił go 19 marca 2020 r. do Microsoft Security Response Center (MSRC). Producent jednak nie uznał go za problem związany bezpieczeństwem. W repozytorium GitHub środowiska uruchomieniowego .NET Core został otwarty problem w czwartek 18 czerwca 2020 r. Szczegóły znajdziecie tutaj.