Rozszerzenie Tagowania Pamięci (MTE)

Reading time: 5 minutes

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks

Podstawowe Informacje

Rozszerzenie Tagowania Pamięci (MTE) zostało zaprojektowane w celu zwiększenia niezawodności i bezpieczeństwa oprogramowania poprzez wykrywanie i zapobieganie błędom związanym z pamięcią, takim jak przepełnienia bufora i luki typu use-after-free. MTE, jako część architektury ARM, zapewnia mechanizm do przypisania małego tagu do każdej alokacji pamięci oraz odpowiedniego tagu do każdego wskaźnika odnoszącego się do tej pamięci. Takie podejście umożliwia wykrywanie nielegalnych dostępu do pamięci w czasie rzeczywistym, znacznie zmniejszając ryzyko wykorzystania takich luk do wykonywania dowolnego kodu.

Jak działa Rozszerzenie Tagowania Pamięci

MTE działa poprzez dzielenie pamięci na małe, stałe bloki, z których każdy ma przypisany tag, zazwyczaj o wielkości kilku bitów.

Gdy tworzony jest wskaźnik wskazujący na tę pamięć, otrzymuje ten sam tag. Tag ten jest przechowywany w niewykorzystanych bitach wskaźnika pamięci, skutecznie łącząc wskaźnik z odpowiadającym mu blokiem pamięci.

https://www.youtube.com/watch?v=UwMt0e_dC_Q

Gdy program uzyskuje dostęp do pamięci za pośrednictwem wskaźnika, sprzęt MTE sprawdza, czy tag wskaźnika pasuje do tagu bloku pamięci. Jeśli tagi nie pasują, wskazuje to na nielegalny dostęp do pamięci.

Tagowanie Wskaźników MTE

Tagi wewnątrz wskaźnika są przechowywane w 4 bitach w górnym bajcie:

https://www.youtube.com/watch?v=UwMt0e_dC_Q

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

Tagi Pamięci MTE

Każde 16B fizycznej pamięci ma odpowiadający tag pamięci.

Tagi pamięci są przechowywane w dedykowanym obszarze RAM (niedostępnym do normalnego użytku). Posiadając tagi 4-bitowe dla każdego 16B tagów pamięci, zajmują one do 3% RAM.

ARM wprowadza następujące instrukcje do manipulacji tymi tagami 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
...

Sprawdzanie trybów

Sync

CPU sprawdza tagi podczas wykonywania instrukcji, jeśli wystąpi niezgodność, zgłasza wyjątek.
Jest to najwolniejszy i najbezpieczniejszy tryb.

Async

CPU sprawdza tagi asynchronicznie, a gdy znajdzie niezgodność, ustawia bit wyjątku w jednym z rejestrów systemowych. Jest szybszy niż poprzedni, ale nie jest w stanie wskazać dokładnej instrukcji, która spowodowała niezgodność, i nie zgłasza wyjątku natychmiast, dając czas atakującemu na dokończenie ataku.

Mixed

???

Przykłady implementacji i wykrywania

Nazywany Hardware Tag-Based KASAN, MTE-based KASAN lub in-kernel 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 przydzielonej przestrzeni jądra oraz do zwróconego wskaźnika.

Należy zauważyć, że oznaczy tylko wystarczającą ilość granulek pamięci (16B każda) dla żądanej wielkości. Jeśli więc żądana wielkość wynosiła 35, a przydzielono blok 60B, oznaczy pierwsze 16*3 = 48B tym tagiem, a reszta będzie oznaczona tzw. nieprawidłowym tagiem (0xE).

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

Dlatego istnieje tylko 14 wartości, które można wykorzystać 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łowej granulki tagu, niezgodność zostanie wykryta. Jeśli uzyska dostęp do innej lokalizacji pamięci, jeśli pamięć ma inny tag (lub tag nieprawidłowy), niezgodność zostanie wykryta. 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 ostatniej granulce przydzielonej pamięci. Jeśli aplikacja zażądała 35B, przydzielono granulę od 32 do 48. Dlatego bajty od 36 do 47 używają tego samego tagu, ale nie zostały zażądane. Jeśli atakujący uzyska dostęp do tych dodatkowych bajtów, nie zostanie to wykryte.

Gdy kfree() jest wykonywane, pamięć jest ponownie oznaczana nieprawidłowym tagiem pamięci, więc w przypadku use-after-free, gdy pamięć jest ponownie uzyskiwana, niezgodność jest wykrywana.

Jednak w przypadku use-after-free, jeśli ten sam blok jest ponownie przydzielany z TYM SAMYM tagiem co wcześniej, atakujący będzie mógł wykorzystać ten dostęp i nie zostanie to wykryte (około 7% szans).

Co więcej, tylko slab i page_alloc używają oznaczonej pamięci, ale w przyszłości będzie to również używane w vmalloc, stack i globals (w momencie nagrania te mogą być nadal narażone na nadużycia).

Gdy niezgodność zostanie wykryta, jądro panikuje, aby zapobiec dalszemu wykorzystywaniu i ponownym próbom wykorzystania (MTE nie ma fałszywych pozytywów).

Odniesienia

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks