Memory Tagging Extension (MTE)
Dowiedz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Dowiedz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Podstawowe informacje
Rozszerzenie oznaczania 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 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 umożliwia 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ą do każdego bloku etykietą, zwykle o kilka bitów.
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:
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 Hardware Tag-Based KASAN, MTE-based KASAN lub in-kernel MTE.
Alokatory jądra (np. 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.
Zauważ, że zostaną oznaczone tylko wystarczające granule pamięci (każdy po 16B) dla żądanej wielkości. Dlatego jeśli żądana wielkość wynosiła 35, a przydzielono kawałek o wielkości 60B, zostaną oznaczone pierwsze 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 przez 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 granulu z nieprawidłowym tagiem, 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 zostanie wykonane kfree()
, pamięć zostanie ponownie oznaczona 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 kawałek 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