Wykorzystanie pustych referencji w jądrze Linuksa
Niedawno ogłoszono, że badacze z zespołu Google Project Zero opracowali metodę wykorzystania luk w jądrze Linuxa, które są spowodowane dereferencją wskaźnika NULL.
Aż do tej pory problemy jądra związane z dereferencjonowaniem wskaźnika NULL nie były przedmiotem należytej uwagi , gdyż uważano za nierealne przekształcanie takich problemów w ataki prowadzące do eskalacji uprawnień lub wykonywania własnego kodu (mapowanie nieuprzywilejowanych procesów do dolnego obszaru przestrzeni adresowej jest zabronione).
Z reguły tego typu błędy powodują generowanie przez jądro ostrzeżeń o błędzie, po czym problematyczne zadania zostają ukończone, a stan przywracany bez konieczności zatrzymywania systemu.
Nowa metoda ataku opiera się na obsłudze stanów „oops” , które mogą skutkować zwiększeniem wartości licznika odwołań (refcount), co z kolei może doprowadzić do przepełnienia licznika i zwolnienia pamięci związanej z refcount.
W tym przypadku eksploatacja sprowadza się do manipulacji typowych dla ataków typu use-after-free (powstaje sytuacja, w której liczba referencji obiektu spada do zera, pamięć zostaje zwolniona, ale w rzeczywistości istnieją działające linki wskazujące na zwolnioną pamięć).
Obecnie, gdy jądro Linuksa wywołuje dereferencję null z kontekstu procesu, generuje błąd oops , który różni się od paniki jądra. Panika występuje, gdy jądro stwierdza, że nie ma bezpiecznego sposobu na kontynuowanie wykonywania i dlatego musi je przerwać. Jednak jądro nie zatrzymuje całego wykonywania podczas błędu oops; zamiast tego próbuje odzyskać sprawność i kontynuuje wykonywanie.
Dereferencja wskaźnika NULL jest tutaj używana jako sposób na wygenerowanie stanu „oops” w kontrolowany sposób. Problem polega na tym, że potrzeba około 232 wywołań stanu „ups”, aby osiągnąć 32-bitowe przepełnienie licznika refcount.
Z praktycznego punktu widzenia, przeprowadzenie ataku z wykorzystaniem proponowanego exploita zajmuje około ośmiu dni ciągłego generowania stanów poza miejscem (OOP) . W przypadku powodzenia exploit umożliwia wykonanie kodu na poziomie jądra.
Dereferencja wskaźnika NULL używana w exploicie została naprawiona w październiku, ale ponieważ podobne problemy nie są rzadkością i wcześniej były traktowane jako błędy, a nie luki w zabezpieczeniach, programiści dodadzą ogólną ochronę jądra Linuksa, aby zapobiec atakom manipulującym generowaniem „oops ”.
W przypadku zadania oznacza to odrzucenie istniejącego stosu jądra i przejście bezpośrednio do make_task_dead, który wywołuje funkcję do_exit. Jądro wyśle również do dmesg dziennik awarii i ślad jądra pokazujący, w jakim stanie znajdowało się jądro, gdy wystąpił błąd. Może się to wydawać dziwnym wyborem, gdy wyraźnie wystąpiło uszkodzenie pamięci; jednak intencją jest ułatwienie wykrywania i rejestrowania błędów jądra zgodnie z filozofią, że działający system jest znacznie łatwiejszy do debugowania niż uszkodzony.
W szczególności jądro 6.2 wprowadza zmiany ograniczające maksymalną liczbę „oopsów” . Po osiągnięciu limitu, który domyślnie wynosi 10 000 „oopsów” (można to zmienić za pomocą parametru oops_limit, jeśli jest to pożądane), jądro zainicjuje przejście w stan „paniki”, a następnie nastąpi restart, który uniemożliwi wykonanie liczby iteracji wymaganej do zresetowania licznika odwołań do zera.
Planowane jest również przeniesienie ograniczenia na wcześniej wydane, ale nadal obsługiwane gałęzie jądra, a także pakiety jądra popularnych dystrybucji.
Na koniec, jeśli chcesz dowiedzieć się więcej na ten temat , możesz znaleźć szczegóły pod poniższym linkiem.