Memory Tagging Extension (MTE)

Zacznij od zera i stań się ekspertem od hakowania AWS dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

Rozszerzenie oznaczania pamięci (MTE) zostało zaprojektowane w celu poprawy niezawodności i bezpieczeństwa oprogramowania poprzez wykrywanie i zapobieganie błędom związanym z pamięcią, takim jak przepełnienia bufora i podatności typu użyj-po-zwolnieniu. MTE, jako część architektury ARM, zapewnia mechanizm dołączania małej etykiety do każdej alokacji pamięci oraz odpowiadającej etykiety do każdego wskaźnika odnoszącego się do tej pamięci. Ten podejście pozwala na wykrywanie nielegalnych dostępów do pamięci w czasie wykonywania, znacznie zmniejszając ryzyko wykorzystania takich podatności do wykonania arbitralnego kodu.

Jak działa rozszerzenie oznaczania pamięci

MTE działa poprzez podział pamięci na małe bloki o stałym rozmiarze, z przypisaną etykietą do każdego bloku, zazwyczaj kilka bitów w rozmiarze.

Gdy tworzony jest wskaźnik wskazujący na tę pamięć, otrzymuje on tę samą etykietę. Ta etykieta jest przechowywana w nieużywanych bitach wskaźnika pamięci, efektywnie łącząc wskaźnik z odpowiadającym mu blokiem pamięci.

Gdy program uzyskuje dostęp do pamięci za pomocą wskaźnika, sprzęt MTE sprawdza, czy etykieta wskaźnika odpowiada etykiecie bloku pamięci. Jeśli etykiety się nie zgadzają, oznacza to nielegalny dostęp do pamięci.

Etykiety wskaźników MTE

Etykiety wewnątrz wskaźnika są przechowywane w 4 bitach w górnej bajcie:

Dlatego pozwala to na 16 różnych wartości etykiet.

Etykiety pamięci MTE

Każde 16B pamięci fizycznej ma odpowiadającą etykietę pamięci.

Etykiety pamięci są przechowywane w dedykowanej strefie RAM (niedostępnej do normalnego użytku). Posiadanie etykiet 4 bitów dla każdych 16B etykiet pamięci zajmuje do 3% pamięci RAM.

ARM wprowadza następujące instrukcje do manipulowania tymi etykietami w dedykowanej pamięci RAM:

STG [<Xn/SP>], #<simm>    Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>]       Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP>      Insert Random [pointer] Tag
...

Tryby sprawdzania

Sync

CPU sprawdza tagi podczas wykonywania instrukcji, jeśli wystąpi niezgodność, generowany jest wyjątek. To najwolniejsze i najbardziej bezpieczne.

Async

CPU sprawdza tagi asynchronicznie, a gdy zostanie znaleziona niezgodność, ustawia bit wyjątku w jednym z rejestrów systemowych. Jest to szybsze niż poprzednie, ale nie jest w stanie wskazać dokładnej instrukcji, która spowodowała niezgodność, i nie generuje wyjątku natychmiast, dając trochę czasu atakującemu na ukończenie ataku.

Mixed

???

Przykłady implementacji i wykrywania

Nazywane sprzętowym KASAN opartym na tagach, KASAN opartym na MTE lub w jądrze MTE. Alokatory jądra (takie jak kmalloc) będą wywoływać ten moduł, który przygotuje tag do użycia (losowo) i dołączy go do zaalokowanej przestrzeni jądra oraz do zwróconego wskaźnika.

Należy zauważyć, że zostaną oznaczone tylko wystarczające granule pamięci (16B każdy) dla żądanego rozmiaru. Dlatego jeśli żądany rozmiar wynosił 35, a przydzielono kawałek o rozmiarze 60B, zostanie oznaczonych pierwszych 16*3 = 48B tym tagiem, a reszta zostanie oznaczona tzw. nieprawidłowym tagiem (0xE).

Tag 0xF to wskaźnik dopasowania wszystkich. Pamięć z tym wskaźnikiem pozwala na użycie dowolnego tagu do dostępu do swojej pamięci (brak niezgodności). Może to uniemożliwić wykrycie ataku MET, jeśli ten tag jest używany w atakowanej pamięci.

Dlatego istnieje tylko 14 wartości, które można użyć do generowania tagów, ponieważ 0xE i 0xF są zarezerwowane, co daje prawdopodobieństwo ponownego użycia tagów wynoszące 1/17 -> około 7%.

Jeśli jądro uzyska dostęp do nieprawidłowego granulu tagu, zostanie wykryta niezgodność. Jeśli uzyska dostęp do innej lokalizacji pamięci, a pamięć ma inny tag (lub nieprawidłowy tag), zostanie wykryta niezgodność. Jeśli atakujący ma szczęście i pamięć używa tego samego tagu, nie zostanie to wykryte. Szanse wynoszą około 7%.

Inny błąd występuje w ostatnim granulu zaalokowanej pamięci. Jeśli aplikacja zażądała 35B, otrzymała granul od 32 do 48. Dlatego bajty od 36 do 47 używają tego samego tagu, ale nie były żądane. Jeśli atakujący uzyska dostęp do tych dodatkowych bajtów, nie zostanie to wykryte.

Gdy wywoływane jest kfree(), pamięć jest ponownie oznaczana nieprawidłowym tagiem pamięci, więc w przypadku użycia po zwolnieniu, gdy pamięć zostanie ponownie dostępna, zostanie wykryta niezgodność.

Jednak w przypadku użycia po zwolnieniu, jeśli ten sam fragment zostanie ponownie zaalokowany z TAKIM SAMYM tagiem jak wcześniej, atakujący będzie mógł skorzystać z tego dostępu, a to nie zostanie wykryte (około 7% szans).

Ponadto tylko slab i page_alloc używają oznaczonej pamięci, ale w przyszłości będzie to również stosowane w vmalloc, stack i globals (w momencie nagrania wciąż można je nadużywać).

Gdy zostanie wykryta niezgodność, jądro zawiesi się, aby zapobiec dalszemu wykorzystaniu i próbom wykorzystania luki (MTE nie generuje fałszywych alarmów).

Referencje

Last updated