Elementrica
03Realizacje04Referencje05Firma06Aktualności07Kontakt
PLENDE

LegacyHive: zwykły użytkownik montuje ul administratora, a łatki nie ma

ElementricaElementrica6 min
LegacyHive: zwykły użytkownik montuje ul administratora, a łatki nie ma

14 lipca Microsoft zamknął ponad 600 podatności. Kilka godzin później badacz podpisujący się Nightmare Eclipse (albo Chaotic Eclipse, zależnie od konta, które akurat mu nie zniknęło) wrzucił do sieci PoC działający na systemach z tymi właśnie poprawkami. Nazwał to LegacyHive. Do dziś nie ma dla tego numeru CVE ani biuletynu Microsoftu.

To jest błąd w usłudze profili użytkowników, ProfSvc. Ta sama usługa, która przy logowaniu wczytuje twoje tapety, skróty i ustawienia Worda. Okazuje się, że da się ją przekonać, żeby wczytała cudze.

Co ten exploit naprawdę robi

W Windowsie „hive” (ul) to plik z fragmentem rejestru. Twoje ustawienia siedzą w NTUSER.DAT i UsrClass.dat, ustawienia kolegi z sąsiedniego konta w jego własnych plikach, i system pilnuje, żebyście sobie nawzajem do nich nie zaglądali.

LegacyHive to pilnowanie omija. Atakujący podmienia wartość wskazującą ścieżkę do danych aplikacji, przekierowuje usługę w przestrzeń nazw menedżera obiektów, a potem czeka na moment, w którym ProfSvc idzie po plik. Ten moment przechwytuje przez oplock, czyli blokadę oportunistyczną na pliku-wabiku, i w ułamku sekundy podmienia link symboliczny. Usługa działa jako SYSTEM, więc otwiera to, co jej podstawiono. Ul ofiary ląduje w classes root atakującego, z prawem zapisu.

Klasyczny wyścig o plik, tyle że wygrywa go strona, która nie powinna nawet stanąć na starcie.

W uproszczeniu logika ataku sprowadza się do jednego: przekonać usługę, żeby wczytała podstawiony plik do gałęzi profilu. Poniższy schemat pokazuje samą ideę, nie działający kod.

// Uproszczony schemat logiczny ataku LegacyHive
// Atakujący manipuluje usługą profili, aby załadować celowy plik hive
// do gałęzi HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
void TriggerLegacyHive() {
    std::string targetUser = "Administrator";
    std::string maliciousHivePath = "C:\\temp\\fake_hive";

    // Próba wymuszenia załadowania ula w kontekście obecnego procesu
    if (LoadUserHive(targetUser, maliciousHivePath)) {
        printf("Success: Target hive mounted in current user classes root.\n");
    }
}

Prawdziwy exploit jest znacznie bardziej pokrętny, bo cały ciężar leży w zsynchronizowaniu podmiany linku z momentem, w którym usługa sięga po plik. Schemat pomija tę część celowo.

Podobny błąd Microsoft łatał w 2015 roku jako CVE-2015-0004. Ta sama klasa, nowa droga dojścia.

Czego ten exploit nie robi

Tu zaczyna się część, którą większość nagłówków pomija.

Opublikowany PoC jest celowo okrojony. Wymaga poświadczeń jeszcze jednego zwykłego użytkownika i nazwy trzeciego konta, a montuje tylko UsrClass.dat. Autor twierdzi, że oryginalna wersja nie potrzebowała żadnych dodatkowych haseł i brała dowolny ul, ale tej wersji nie pokazał.

Matei Badanoiu z Pentest-Tools ujął to trzeźwo: dla kogoś, kto już ma przyczółek w środowisku, to naprawdę użyteczny prymityw, natomiast sklejanie go z kradzieżą poświadczeń i utrzymaniem dostępu w jedno „pełne przejęcie” to raczej ambicja niż to, co faktycznie wypuszczono.

Zgadzam się. Sam z siebie LegacyHive nie robi z nikogo Domain Admina i nie wjeżdża do firmy z internetu. Trzeba już siedzieć na maszynie, mieć konto i mieć drugie konto do wykorzystania.

To dlaczego w ogóle się tym przejmować

Bo ten warunek wstępny jest w praktyce banalny. Konto przejęte phishingiem, laptop przekazany po odejściu pracownika, stacja w laboratorium, na której loguje się pół działu, konto techniczne używane przez trzy osoby. Przyczółek na poziomie zwykłego użytkownika rzadko jest szczytem trudności, to punkt wyjścia.

A kiedy już go masz, prawo zapisu do gałęzi klas innego użytkownika jest zaskakująco mocne. Will Dormann, który przetestował exploit, pokazał to na przykładzie: można powiązać pliki .txt z kalkulatorem, więc administrator loguje się, otwiera notatkę i uruchamia twój kod. Kalkulator jest oczywiście żartem. Zamiast niego można wpisać cokolwiek, łącznie z rzeczami, które nie wymagają, żeby ofiara w cokolwiek klikała.

Czyli mechanizm jest taki: masz konto stażysty, czekasz aż na tej samej maszynie zaloguje się ktoś z uprawnieniami lokalnego admina, i dostajesz wykonanie kodu w jego kontekście. Stamtąd LSASS, poświadczenia, ruch boczny. Znane od lat, tylko wejście nowe.

Dla zarządu przekłada się to na jedno zdanie: separacja kont na wspólnie użytkowanych stacjach, na której wielu z nas opiera model ryzyka, w tym scenariuszu nie działa, a Microsoft nie wydał jeszcze nic, co by to zmieniło.

Co z tym zrobić, skoro nie ma łatki

Standardowa rada „aktualizuj systemy” tym razem nie pomoże, bo aktualizacje już masz i exploit działa właśnie na nich. Zostaje ograniczanie warunków wstępnych i wykrywanie.

Zacznij od inwentaryzacji stacji, na których loguje się więcej niż jedna osoba. To one są tu celem, nie serwery. Stanowiska współdzielone, komputery w salach szkoleniowych, maszyny serwisowe, wszystko z historią kilku profili lokalnych.

Sprawdź, gdzie konta administracyjne logują się interaktywnie na zwykłych stacjach roboczych. Każde takie logowanie zostawia profil, a profil to ul, który da się zamontować. Jeśli admin domenowy loguje się na maszynie użytkownika, żeby „coś szybko sprawdzić”, masz problem starszy niż LegacyHive.

Ustaw w EDR alert na próby ładowania uli rejestru przez procesy użytkownika i na nietypowe zmiany wartości ścieżek profilu w ProfileList. Tego wyścigu nie zablokujesz, ale ślad po nim zostaje.

Przejrzyj, kto ma lokalnego admina i czy to nadal ma uzasadnienie. Nie dlatego, że to zatrzyma ten konkretny exploit, tylko dlatego, że skraca łańcuch po nim.

I odłóż na bok pomysł, że publikacja zniknie z sieci. Konta tego badacza były już kasowane z GitHuba i GitLaba, a on wraca z kolejnym narzędziem. Z sześciu jego wcześniejszych zero-dayów trzy zostały użyte w atakach, zanim wyszły poprawki.

Na koniec

Piszę to w dniu, w którym Microsoft nadal milczy, więc część powyższego może się zdezaktualizować w ciągu tygodnia. Jeśli biuletyn wyjdzie, zaktualizujemy wpis.

Zostaje pytanie, na które warto odpowiedzieć sobie przed poniedziałkiem: ile masz w firmie stacji, na których w ostatnim półroczu zalogował się i zwykły użytkownik, i ktoś z uprawnieniami admina? Jeśli nie wiesz, to jest dokładnie ta liczba, od której zaczynamy w testach wewnętrznych.

Ile masz stacji, na których loguje się użytkownik i admin?

Umów bezpłatną konsultację: 30 minut, konkretnie i bez zobowiązań. Pokażemy, jak w teście wewnętrznym sprawdzamy, dokąd naprawdę prowadzi jedno zwykłe konto na współdzielonej stacji.

Następny
wp2shell: jedno anonimowe żądanie i WordPress przestaje być twój