Abstrakt
1. Wprowadzenie
2. Podstawy
3. Model Zagrożeń
4. Znajdowanie Gadżetów Wycieku Tagów
5. Gadżety TIKTAG
6. Ataki w Rzeczywistym Świecie
6.1. Atakowanie Chrome
7. Ocena
8. Prace Powiązane
9. Podsumowanie i Bibliografia
\
Aby zademonstrować możliwość wykorzystania gadżetów TIKTAG w mitygacji opartej na MTE, ta sekcja przedstawia dwa rzeczywiste ataki na Chrome i jądro Linuxa (Rysunek 9). Istnieje kilka wyzwań związanych z uruchomieniem rzeczywistych ataków przy użyciu gadżetów TIKTAG. Po pierwsze, gadżety TIKTAG powinny być wykonywane w docelowej przestrzeni adresowej, co wymaga od atakującego skonstruowania lub znalezienia gadżetów w systemie docelowym. Po drugie, atakujący powinien kontrolować i obserwować stan pamięci podręcznej, aby wyciec wyniki sprawdzania tagów. W dalszej części demonstrujemy rzeczywiste ataki wykorzystujące gadżety TIKTAG na dwóch rzeczywistych systemach: przeglądarce Google Chrome (§6.1) i jądrze Linuxa (§6.2), oraz omawiamy strategie mitygacji.
\ 6.1. Atakowanie Chrome
Przeglądarka Przeglądarka internetowa jest główną powierzchnią ataku dla ataków opartych na sieci, ponieważ przetwarza niezaufane treści internetowe, takie jak JavaScript i HTML. Najpierw przedstawiamy przegląd modelu zagrożeń (§6.1.1) i dostarczamy gadżet TIKTAG skonstruowany w silniku JavaScript V8 (§6.1.2). Następnie demonstrujemy skuteczność gadżetów TIKTAG w wykorzystywaniu przeglądarki (§6.1.3) i omawiamy strategie mitygacji (§6.1.4).
\ ==6.1.1. Model Zagrożeń.== Postępujemy zgodnie z typowym modelem zagrożeń ataków na przeglądarkę Chrome, gdzie atakujący ma na celu wykorzystanie podatności na uszkodzenie pamięci w procesie renderowania. Zakładamy, że użytkownik będący ofiarą odwiedza kontrolowaną przez atakującego stronę internetową, która serwuje złośliwą stronę. Strona zawiera spreparowane HTML i JavaScript, które wykorzystują podatności na uszkodzenie pamięci w procesie renderowania ofiary. Zakładamy, że wszystkie najnowocześniejsze techniki mitygacji Chrome są wdrożone, w tym ASLR [18], CFI [15], izolacja witryn [53] i piaskownica V8 [56]. Dodatkowo, jako ortogonalna obrona, zakładamy, że proces renderowania włącza losowe tagowanie MTE w PartitionAlloc [2].
\ ==6.1.2. Konstruowanie Gadżetu TIKTAG.== W środowisku JavaScript V8, TIKTAG-v2 został pomyślnie skonstruowany i wyciekł tagi MTE dowolnego adresu pamięci. Jednak nie znaleźliśmy możliwego do skonstruowania gadżetu TIKTAG-v1, ponieważ ścisłe ograniczenie czasowe między BR i CHECK nie było możliwe do osiągnięcia w naszej technice spekulatywnego ucieczki z piaskownicy V8 (§A).
Gadżet V8 TikTag-v2. Rysunek 8 przedstawia gadżet TIKTAG-v2 skonstruowany w silniku JavaScript V8 i jego pseudo-kod C po kompilacji JIT. Za pomocą tego gadżetu atakujący może dowiedzieć się, czy zgadywany tag Tg pasuje do tagu Tm przypisanego do target_addr. Atakujący przygotowuje trzy tablice: slow, victim, probe oraz wartość idx. slow to Unit8Array o długości 64 i jest dostępny w BR w celu wywołania błędnej predykcji rozgałęzienia. victim to Float64Array o długości 64, który jest dostępny w celu wywołania przekazywania store-to-load. probe to Uint8Array o długości 512 i jest dostępny w
\ TEST w celu wycieku wyniku sprawdzenia tagu. Wartość idx typu Number jest używana do dostępu poza granicami victim. Wartość idx jest wybierana tak, że victim[idx] wskazuje na targetaddr z zgadywanym tagiem Tg (tj. (Tg«56)|targetaddr). Aby spekulatywnie uzyskać dostęp do target_addr poza piaskownicą V8, wykorzystaliśmy technikę spekulatywnego ucieczki z piaskownicy V8, którą odkryliśmy podczas naszych badań, którą szczegółowo opisujemy w §A. Linia 8 Rysunku 8a jest blokiem BR gadżetu TIKTAG-v2, wywołującym błędną predykcję rozgałęzienia za pomocą slow[0].
\ Linie 12-13 to blok CHECK, który wykonuje przekazywanie store-to-load za pomocą victim[idx], uzyskując dostęp do target_addr z zgadywanym tagiem Tg. Gdy ten kod jest kompilowany przez JIT (Rysunek 8b), przeprowadzane jest sprawdzenie granic, porównujące idx z victim.length. Jeśli idx jest indeksem poza granicami, kod zwraca undefined, ale jeśli załadowanie pola victim.length zajmuje dużo czasu, procesor spekulatywnie wykonuje następne instrukcje store i load.
\ Następnie linia 17 implementuje blok TEST, który uzyskuje dostęp do probe z przekazaną wartością val jako indeksem. Ponownie poprzedzone jest sprawdzenie granic val względem długości probe, ale to sprawdzenie się udaje, ponieważ PROBEOFFSET jest mniejszy niż długość tablicy probe. W rezultacie probe[PROBEOFFSET] jest buforowany tylko wtedy, gdy przekazywanie store-to-load się udaje, co ma miejsce, gdy Tg pasuje do Tm.
\ ==6.1.3. Atak ominięcia MTE Chrome.== Rysunek 9a ilustruje ogólny atak ominięcia MTE na przeglądarkę Chrome z prymitywem dowolnego wycieku tagów gadżetów TIKTAG. Zakładamy podatność przepełnienia bufora w procesie renderowania, gdzie wykorzystanie podatności czasowej (np. use-after-free) jest w dużej mierze takie samo. Podatność przepełnia wskaźnik (tj. vuln_ptr) do podatnego obiektu (tj. objvuln), uszkadzając sąsiedni obiekt (tj. objtarget).
\ Przy egzekwowaniu MTE przez PartitionAlloc dwa obiekty mają różne tagi z prawdopodobieństwem 14/15. Aby uniknąć wywołania wyjątku, atakujący musi upewnić się, że tagi objvuln i objtarget są takie same. TIKTAG-v2 można wykorzystać do wycieku tagu objvuln ( 1 ) i objtarget ( 2 ). Jeśli oba wycieknięte tagi są takie same, atakujący wykorzystuje podatność, która nie wywoła błędu sprawdzania tagu ( 3 ). W przeciwnym razie atakujący zwalnia i ponownie alokuje objtarget i wraca do pierwszego kroku, dopóki tagi nie będą pasować.
\ ==Wyzwalanie Kanału Bocznego Pamięci Podręcznej.== Aby pomyślnie wykorzystać gadżet TIKTAG, atakujący musi spełnić następujące wymagania:
i) trening rozgałęzienia,
ii) kontrola pamięci podręcznej i
iii) pomiar pamięci podręcznej. Wszystkie trzy wymagania mogą być spełnione w JavaScript.
Po pierwsze, atakujący może wytrenować predyktor rozgałęzienia, uruchamiając gadżet z niezerowym slow[0] i idx w granicach, i wywołać błędną predykcję rozgałęzienia w BR z wartością zerową w slow[0] i idx poza granicami.
Po drugie, atakujący może usunąć linie pamięci podręcznej slow[0], victim.length i probe[PROBE_OFFSET] za pomocą technik usuwania pamięci podręcznej JavaScript [8, 21, 70].
Po trzecie, atakujący może zmierzyć stan pamięci podręcznej probe[PROBE_OFFSET] za pomocą zegara wysokiej rozdzielczości opartego na SharedArrayBuffer [16, 58].
\ ==Wykorzystywanie Podatności Uszkodzenia Pamięci.== Mając wycieknięte tagi MTE, atakujący może wykorzystać przestrzenne i czasowe podatności uszkodzenia pamięci w rendererze. Strategia ataku jest w dużej mierze taka sama jak w tradycyjnych atakach uszkodzenia pamięci, ale powinna zapewnić, że podatność nie wywołuje błędu sprawdzania tagu, wykorzystując wycieknięte tagi. Więcej szczegółów strategii ataku podajemy w §C.
\ ==6.1.4. Mitygacja.== Aby złagodzić ataki ominięcia MTE oparte na gadżetach TIKTAG w procesie renderowania przeglądarki, można zastosować następujące mitygacje:
i) Piaskownica uwzględniająca spekulatywne wykonanie: Aby powstrzymać atakujących przed uruchamianiem ataków opartych na TIKTAG ze środowiska w piaskownicy, takiego jak piaskownica V8, piaskownica może zostać wzmocniona poprzez zapobieganie jakiemukolwiek spekulatywnemu dostępowi do pamięci poza regionem pamięci piaskownicy. Chociaż nowoczesne przeglądarki internetowe stosują piaskownicę do izolowania niezaufanych treści internetowych od renderera, często pomijają ścieżki spekulatywne.
\ Na przykład piaskownica Chrome V8 [56] i piaskownica Safari Webkit [1] nie w pełni pośredniczą w ścieżkach spekulatywnych [27]. W oparciu o obecne techniki kompresji wskaźników [64], ścieżki spekulatywne mogą być ograniczone do regionu piaskownicy poprzez maskowanie wysokich bitów wskaźników.
\ ii) Bariera spekulacji: Jak sugerowano w §5, umieszczenie bariery spekulacji po BR dla potencjalnych gadżetów TIKTAG może zapobiec atakom spekulatywnego wycieku tagów. Jednak ta mitygacja może nie być stosowalna w środowisku przeglądarki krytycznym pod względem wydajności, ponieważ może wprowadzić znaczny narzut wydajnościowy.
\ iii) Zapobieganie konstrukcji gadżetów: Jak sugerowano w §5.2, gadżet TIKTAG-v2 można złagodzić poprzez wypełnienie instrukcji między instrukcjami store i load. Gadżet TIKTAGv1, chociaż nie znaleźliśmy możliwego do wykorzystania, można złagodzić poprzez wypełnienie instrukcji między rozgałęzieniem a dostępami do pamięci, jak opisano w §5.1.
\ 6.2. Atakowanie Jądra Linux
Jądro Linuxa na ARM jest szeroko stosowane w urządzeniach mobilnych, serwerach i urządzeniach IoT, co czyni je atrakcyjnym celem ataku. Wykorzystanie podatności uszkodzenia pamięci w jądrze może eskalować uprawnienia użytkownika, a zatem MTE jest obiecującym mechanizmem ochrony dla jądra Linuxa. Ataki oparte na TIKTAG przeciwko jądru Linuxa stanowią unikalne wyzwania różniące się od ataku na przeglądarkę (§6.1).
\ Dzieje się tak, ponieważ przestrzeń adresowa atakującego jest odizolowana od przestrzeni adresowej jądra, w której zostanie wykonany gadżet. W dalszej części najpierw przedstawiamy przegląd modelu zagrożeń jądra Linuxa (§6.2.1) i dostarczamy proof-of-concept gadżetu TIKTAG, który odkryliśmy w jądrze Linuxa (§6.2.2). Na koniec demonstrujemy skuteczność gadżetów TIKTAG w wykorzystywaniu podatności jądra Linuxa (§6.2.3).
\ ==6.2.1. Model Zagrożeń.== Model zagrożeń tutaj jest w dużej mierze taki sam jak w przypadku typowych ataków eskalacji uprawnień przeciwko jądru. W szczególności koncentrujemy się na jądrze Android Linux opartym na ARM, wzmocnionym domyślnymi zabezpieczeniami jądra (np. KASLR, SMEP, SMAP i CFI). Dodatkowo zakładamy, że jądro jest wzmocnione rozwiązaniem losowego tagowania MTE, podobnym do gotowych do produkcji rozwiązań MTE, Scudo [3].
\ Aby być konkretnym, każdy obiekt pamięci jest losowo tagowany, a losowy tag jest przypisywany, gdy obiekt jest zwalniany, zapobiegając tym samym zarówno przestrzennym, jak i czasowym uszkodzeniom pamięci. Atakujący jest w stanie uruchomić nieuprawniony proces i ma na celu eskalację swoich uprawnień poprzez wykorzystanie podatności uszkodzenia pamięci w jądrze. Zakłada się, że atakujący zna podatności uszkodzenia pamięci jądra, ale nie zna żadnego tagu MTE pamięci jądra. Wyzwolenie uszkodzenia pamięci między obiektami jądra z
\ niedopasowanymi tagami wywołałoby błąd sprawdzania tagu, co jest niepożądane w rzeczywistych eksploitach. Jednym krytycznym wyzwaniem w tym ataku jest to, że gadżet powinien być skonstruowany poprzez ponowne użycie istniejącego kodu jądra i wykonany przez wywołania systemowe, które atakujący może wywołać. Ponieważ architektura ARMv8 rozdziela tablice stron użytkownika i jądra, gadżety przestrzeni użytkownika nie mogą spekulatywnie uzyskać dostępu do pamięci jądra. Ta konfiguracja bardzo różni się od modelu zagrożeń atakowania przeglądarki (§6.1), który wykorzystał kod dostarczony przez atakującego do skonstruowania gadżetu. Wykluczyliśmy również konstrukcję gadżetu opartą na eBPF [17, 28], ponieważ eBPF nie jest dostępny dla nieuprawnionego procesu Android [33].
\ ==6.2.2. Gadżet Kernel TikTag==. Jak opisano w §4.1, gadżety TIKTAG powinny spełniać kilka wymagań, a każde wymaganie wiąże się z wyzwaniami w środowisku jądra.
Po pierwsze, w BR należy wywołać błędną predykcję rozgałęzienia za pomocą cond_ptr, który powinien być kontrolowany z przestrzeni użytkownika. Ponieważ najnowsze procesory AArch64 izolują trening predykcji rozgałęzień między użytkownikiem a jądrem [33], trening rozgałęzienia musi być wykonywany z przestrzeni jądra.
Po drugie, w CHECK, guessptr powinien być wyłuskany. guessptr powinien być spreparowany z przestrzeni użytkownika tak, aby zawierał zgadywany tag (Tg) i wskazywał na adres jądra (tj. target_addr) w celu wycieku tagu (Tm). W przeciwieństwie do środowiska JavaScript przeglądarki (§6.1), dane dostarczone przez użytkownika są silnie oczyszczane w wywołaniach systemowych, więc trudno jest utworzyć dowolny wskaźnik jądra.
\ Na przykład accessok() zapewnia, że wskaźnik dostarczony przez użytkownika wskazuje na przestrzeń użytkownika, a makro arrayindexnospec zapobiega spekulatywnemu dostępowi poza granicami z indeksem dostarczonym przez użytkownika. Zatem guessptr powinien być istniejącym wskaźnikiem jądra, konkretnie podatnym wskaźnikiem powodującym uszkodzenie pamięci. Na przykład można użyć wiszącego wskaźnika w use-after-free (UAF) lub wskaźnika poza granicami w przepełnieniu bufora. Wreszcie, w TEST, testptr powinien być wyłuskany, a testptr powinien być dostępny z przestrzeni użytkownika. Aby ułatwić pomiar stanu pamięci podręcznej, test_ptr powinien być wskaźnikiem przestrzeni użytkownika dostarczonym przez argument wywołania systemowego.
\ ==Odkryte Gadżety.== Ręcznie przeanalizowaliśmy kod źródłowy jądra Linuxa, aby znaleźć gadżet TIKTAG spełniający wyżej wymienione wymagania. W rezultacie znaleźliśmy jeden potencjalnie możliwy do wykorzystania gadżet TIKTAG-v1 w sndtimeruserread() (Rysunek 10). Ten gadżet spełnia wymagania TIKTAG-v1 (§5.1). W linii 10 (tj. BR) instrukcja switch wywołuje błędną predykcję rozgałęzienia z kontrolowaną przez użytkownika wartością tu->tread (tj. condptr). W liniach 14-17 (tj. CHECK), tread (tj. guessptr) jest wyłuskiwany przez cztery instrukcje load. tread wskazuje na obiekt struct sndtimer_tread64, który atakujący może dowolnie alokować i zwalniać.
\ Jeśli podatność czasowa przekształca tread w wiszący wskaźnik, można go użyć jako guessptr. W linii 20 (tj. TEST) wskaźnik przestrzeni użytkownika buffer (tj. testptr) jest wyłuskiwany w copytouser. Ponieważ ten gadżet nie jest bezpośrednio dostępny z przestrzeni użytkownika, dokonaliśmy niewielkiej modyfikacji kodu jądra; usunęliśmy wczesny zwrot dla przypadku domyślnego w linii 6. To zapewnia, że bufor jest dostępny tylko w ścieżce spekulatywnej, aby zaobserwować różnicę stanu pamięci podręcznej spowodowaną spekulatywnym wykonaniem.
\ Chociaż ta modyfikacja nie jest realistyczna w rzeczywistym scenariuszu, demonstruje potencjalną możliwość wykorzystania gadżetu, jeśli zostaną wprowadzone podobne zmiany kodu. Odkryliśmy kilka innych potencjalnie możliwych do wykorzystania gadżetów, ale nie byliśmy w stanie zaobserwować różnicy stanu pamięci podręcznej między dopasowaniem a niedopasowaniem tagu. Mimo to uważamy, że istnieje duży potencjał wykorzystania tych gadżetów. Uruchomienie ataków opartych na TIKTAG wymaga złożonej i wrażliwej inżynierii, dlatego nie byliśmy w stanie przeprowadzić eksperymentów we wszystkich możliwych przypadkach.
\ W szczególności TIKTAG-v1 polega na kurczeniu spekulacji na zdarzeniach błędnej ścieżki, które mogą również obejmować błędy translacji adresów lub inne wyjątki w ścieżce błędnej predykcji rozgałęzienia. Ponieważ wywołania systemowe obejmują złożone przepływy sterowania, kurczenie spekulacji może nie być wyzwalane zgodnie z oczekiwaniami. Ponadto kilka gadżetów może stać się możliwych do wykorzystania, gdy zmieni się kod jądra. Na przykład gadżet TIKTAG-v1 w ip6mr_ioctl() nie wykazywał zachowania wycieku tagu MTE, gdy był wywoływany ze swojej ścieżki wywołania systemowego (tj. ioctl). Jednak gadżet miał wyciek tagu, gdy został przeniesiony do innych wywołań systemowych (np. write) z prostym przepływem sterowania.
\ ==6.2.3. Atak ominięcia MTE jądra.== Rysunek 9b ilustruje ataki ominięcia MTE na jądro Linuxa. Biorąc za przykład podatność use-afterfree, zakładamy, że atakujący zidentyfikował odpowiedni gadżet TIKTAG, SysTikTagUAF(), zdolny do wycieku wyniku sprawdzenia tagu wiszącego wskaźnika utworzonego przez podatność. Na przykład gadżet TIKTAG-v1 w sndtimeruser_read() (Rysunek 10) może wyciec wynik sprawdzenia tagu tread, który może stać się wiszącym wskaźnikiem przez podatność use-after-free lub double-free.
\ Atak przebiega następująco: Najpierw atakujący zwalnia obiekt jądra (tj. objvuln) i pozostawia jego wskaźnik (tj. vuln_ptr) jako wiszący wskaźnik ( 1 ). Następnie atakujący alokuje inny obiekt jądra (tj. objtarget) pod adresem objvuln za pomocą SysAllocTarget() ( 2 ). Następnie atakujący wywołuje SysTikTag() z buforem przestrzeni użytkownika (tj. ubuf) ( 3 ) i wycieka wynik sprawdzenia tagu (tj. Tm == Tg) mierząc opóźnienie dostępu ubuf ( 4 ). Jeśli tagi pasują, atakujący wyzwala SysExploitUAF(), wywołanie systemowe wykorzystujące podatność use-after-free ( 5 ). W przeciwnym razie atakujący ponownie alokuje objtarget, dopóki tagi nie będą pasować.
\ ==Wyzwalanie Kanału Bocznego Pamięci Podręcznej.== Jak w §6.1.3, pomyślne wykorzystanie gadżetu TIKTAG wymaga i) treningu rozgałęzienia, ii) kontroli pamięci podręcznej i iii) pomiaru pamięci podręcznej. W przypadku treningu rozgałęzienia atakujący może wytrenować predyktor rozgałęzienia i wywołać spekulację z warunkami rozgałęzienia kontrolowanymi przez użytkownika z przestrzeni użytkownika. W przypadku kontroli pamięci podręcznej atakujący może opróżnić bufor przestrzeni użytkownika (tj. ubuf), podczas gdy adres pamięci jądra można usunąć za pomocą odbijania linii pamięci podręcznej [25]. W przypadku pomiaru pamięci podręcznej opóźnienie dostępu ubuf można zmierzyć za pomocą licznika wirtualnego (tj. CNTVCT_EL0) lub timera opartego na liczniku pamięci (tj. rozdzielczość zbliżona do cyklu procesora).
\ ==Wykorzystywanie Podatności Uszkodzenia Pamięci.== Gadżety TIKTAG umożliwiają ominięcie MTE i wykorzystanie podatności uszkodzenia pamięci jądra. Atakujący może wywołać gadżet TIKTAG w jądrze, aby spekulatywnie wywołać uszkodzenie pamięci i uzyskać wynik sprawdzenia tagu. Następnie atakujący może uzyskać wynik sprawdzenia tagu i wywołać uszkodzenie pamięci tylko wtedy, gdy tagi pasują. Szczegółowo opisujemy proces ataku ominięcia MTE jądra Linuxa w §D.
\ ==6.2.4. Mitygacja.== Aby złagodzić gadżet TIKTAG w jądrze Linuxa, deweloperzy jądra powinni rozważyć następujące mitygacje:
i) Bariera spekulacji: Bariery spekulacji mogą skutecznie złagodzić gadżet TIKTAG-v1 w jądrze Linuxa. Aby zapobiec wycieku wyniku sprawdzenia tagu przez atakujących przez bufor przestrzeni użytkownika, funkcje jądra uzyskujące dostęp do adresów przestrzeni użytkownika, takie jak copytouser i copyfromuser, można wzmocnić barierami spekulacji. Jak opisano w §5.1, wyciek wyników sprawdzania tagów za pomocą dostępu store można złagodzić, umieszczając barierę spekulacji przed dostępem store (tj. TEST).
\ Na przykład, aby złagodzić gadżety wykorzystujące copytouser, barierę spekulacji można wstawić przed wywołaniem copytouser. W przypadku gadżetów wykorzystujących dostęp load do bufora przestrzeni użytkownika, bariery łagodzą gadżety, jeśli zostaną wstawione między rozgałęzieniem a dostępem do pamięci jądra (tj. CHECK). Na przykład, aby złagodzić gadżety wykorzystujące copyfromuser, deweloperzy jądra powinni dokładnie przeanalizować bazę kodu jądra, aby znaleźć wzorzec warunkowego rozgałęzienia, dostępu do pamięci jądra i copyfromuser() oraz wstawić barierę spekulacji między rozgałęzieniem a dostępem do pamięci jądra.
\ ii) Zapobieganie konstrukcji gadżetów: Aby wyeliminować potencjalne gadżety TIKTAG w jądrze Linuxa, kod źródłowy jądra może być analizowany i łatany. Ponieważ gadżety TIKTAG mogą być również konstruowane przez optymalizacje kompilatora, można przeprowadzić analizę binarną. Dla każdego odkrytego gadżetu instrukcje mogą być zmienione w kolejności lub można wstawić dodatkowe instrukcje, aby zapobiec konstrukcji gadżetu, zgodnie ze strategiami mitygacji w §5.1 i §5.2.
:::info Autorzy:
:::
:::info Ten artykuł jest dostępny na arxiv na licencji CC 4.0.
:::
\


