Sytuacja wyścigu w module zbierającym elementy bezużyteczne jądra Linux, która może prowadzić do eskalacji uprawnień

Jann Horn z zespołu Google Project Zero, który zidentyfikował luki w zabezpieczeniach Spectre i Meltdown, opublikował technikę wykorzystania luki (CVE-2021-4083) w module zbierającym elementy bezużyteczne jądra Linuksa. Luka wynika z wyścigu podczas czyszczenia deskryptorów plików w gniazdach Unix i potencjalnie umożliwia lokalnemu nieuprzywilejowanemu użytkownikowi wykonanie kodu na poziomie jądra.

Problem jest o tyle interesujący, że oszacowano, że okno czasowe, w którym występuje sytuacja wyścigowa, jest zbyt małe, aby stworzyć prawdziwe exploity, jednak autor badania wykazał, że nawet tak początkowo sceptyczne luki mogą stać się źródłem realnych ataków, jeśli twórca exploita niezbędne umiejętności i czas. Yann Horn pokazał, jak za pomocą filigranowych manipulacji można zredukować sytuację wyścigu występującą podczas jednoczesnego wywoływania funkcji close() i fget() do w pełni nadającej się do wykorzystania luki typu use-after-free i uzyskać dostęp do już uwolnionych danych strukturę wewnątrz jądra.

Podczas zamykania deskryptora pliku podczas jednoczesnego wywoływania funkcji Close() i fget() występuje sytuacja wyścigu. Wywołanie funkcji close() może nastąpić przed wykonaniem fget(), co zdezorientuje moduł zbierający elementy bezużyteczne, ponieważ zgodnie z refcountem struktura pliku nie będzie miała zewnętrznych odniesień, ale pozostanie dołączona do deskryptora pliku, tj. Moduł zbierający elementy bezużyteczne będzie myślał, że ma wyłączny dostęp do struktury, ale w rzeczywistości przez krótki czas pozostały wpis w tabeli deskryptorów plików będzie nadal wskazywał na zwolnienie struktury.

Aby zwiększyć prawdopodobieństwo wejścia w stan wyścigu, zastosowano kilka sztuczek, które pozwoliły zwiększyć prawdopodobieństwo powodzenia eksploatacji do 30% przy wprowadzeniu optymalizacji specyficznych dla systemu. Przykładowo, aby wydłużyć czas dostępu do struktury z deskryptorami plików o kilkaset nanosekund, dane zostały wyrzucone z pamięci podręcznej procesora poprzez zaśmiecenie pamięci podręcznej aktywnością na innym rdzeniu procesora, co umożliwiło pobranie struktury z pamięci, a nie z szybką pamięć podręczną procesora.

Drugą ważną cechą było wykorzystanie przerwań generowanych przez zegar sprzętowy w celu wydłużenia czasu warunku wyścigu. Moment został wybrany tak, aby procedura obsługi przerwań uruchomiła się w przypadku wystąpienia sytuacji wyścigu i przerwała na pewien czas wykonanie kodu. Aby jeszcze bardziej opóźnić powrót kontroli, przy użyciu narzędzia epoll wygenerowano około 50 tysięcy wpisów w kolejce oczekujących, co wymagało przeszukania procedury obsługi przerwań.

Technika wykorzystania luki została ujawniona po 90-dniowym okresie nieujawniania. Problem pojawia się od wersji jądra 2.6.32 i został naprawiony na początku grudnia. Poprawka została uwzględniona w jądrze 5.16, a także została przeniesiona do gałęzi LTS jądra i pakietów jądra dostarczanych w dystrybucjach. Warto zauważyć, że luka została zidentyfikowana podczas analizy podobnego problemu CVE-2021-0920, który objawia się w śmieciarce podczas przetwarzania flagi MSG_PEEK.

Źródło: opennet.ru

Dodaj komentarz