W jądrze Linux odkryto podatność (CVE-2021-3609), która umożliwia lokalnemu użytkownikowi zwiększenie swoich uprawnień w systemie. Problem jest spowodowany warunkiem wyścigu w implementacji protokołu CAN BCM i występuje w wydaniach jądra Linux od 2.6.25 do 5.13-rc6. W dystrybucjach problem na razie pozostaje niezałatwiony (RHEL, Fedora, Debian, Ubuntu, SUSE, Arch).
Badacz, który odkrył lukę, zdołał przygotować exploit do uzyskania praw root na systemach z jądrami Linux 5.4 i nowszymi, udowodniono również możliwość przeprowadzenia udanego ataku na Ubuntu 20.04.02 LTS. Nie wyklucza się możliwości przerobienia exploita, aby działał również na starszych jądrach (w jądrze 5.4 kod CAN BCM (net/can/bcm.c) został przetłumaczony z hrtimer_tasklet na HRTIMER_MODE_SOFT).
Protokół CAN BCM pozwala zarejestrować własny handler wiadomości, które przychodzą przez sieć CAN (controller area network), i przypiąć go do określonego gniazda sieciowego. Po przyjściu wiadomości wywoływana jest funkcja bcm_rx_handler(). Atakujący może wykorzystać stan wyścigu i wymusić zamknięcie gniazda sieciowego w momencie, gdy wykonywana jest bcm_rx_handler(). Podczas zamykania gniazda wywoływana jest funkcja bcm_release(), w której zwalniana jest pamięć przydzielona dla struktur bcm_op i bcm_sock, które są nadal używane w wykonującym się handlerze bcm_rx_handler(). Powstaje sytuacja prowadząca do odniesienia się do już zwolnionego bloku pamięci (use-after-free).
Atak polega na otwarciu dwóch gniazd CAN BCM i powiązaniu ich z interfejsem vcan. W pierwszym gnieździe wykonywane jest wywołanie sendmsg() z flagą RX_SETUP w celu skonfigurowania handlera przychodzących wiadomości CAN, a w drugim gnieździe następuje wywołanie sendmsg() do wysłania wiadomości do pierwszego gniazda. Po przyjściu wiadomości wywoływana jest funkcja bcm_rx_handler(), a atakujący wybiera odpowiedni moment i zamyka pierwsze gniazdo, co prowadzi do uruchomienia bcm_release() i zwolnienia struktur bcm_op i bcm_sock, mimo że praca bcm_rx_handler() jeszcze się nie zakończyła.
Dzięki manipulacjom z zawartością bcm_sock, atakujący może nadpisać wskaźnik na funkcję sk->sk_data_ready(sk), przekierować wykonywanie i przy pomocy technik programowania z orientacją na powroty (ROP – Return-Oriented Programming) zorganizować nadpisanie parametru modprobe_path i doprowadzić do wykonania swojego kodu z uprawnieniami roota. Używając techniki ROP, atakujący nie próbuje umieścić swojego kodu w pamięci, lecz operuje już istniejącymi w załadowanych bibliotekach fragmentami instrukcji maszynowych, kończącymi się instrukcją zwrotu sterowania (zazwyczaj są to końcówki funkcji bibliotecznych). Działanie exploita sprowadza się do budowy łańcucha wywołań podobnych bloków („gadżetów”) w celu uzyskania potrzebnej funkcjonalności.

Do przeprowadzenia ataku wymagany jest dostęp do tworzenia gniazd CAN oraz skonfigurowany interfejs sieciowy vcan. Niezbędne uprawnienia do wykonania ataku mogą być uzyskane przez nieuprzywilejowanego użytkownika w kontenerach, tworzonych w systemach z włączoną obsługą przestrzeni nazw identyfikatorów użytkowników (user namespaces). Na przykład, user namespaces jest domyślnie włączony w Ubuntu i Fedory, ale nieaktywny w Debianie i RHEL.
Źródło: opennet.ru
