Badacze z zespołu Google Project Zero opublikowali metodę wykorzystania podatności (CVE-2020-29661) w implementacji obsługi ioctl TIOCSPGRP w podsystemie tty jądra Linux oraz szczegółowo przeanalizowali mechanizmy ochronne, które mogłyby zablokować takie podatności.
Problematyczny błąd został naprawiony w jądrze Linux już 3 grudnia ubiegłego roku. Problem dotyczy jąder do wersji 5.9.13, ale większość dystrybucji rozwiązała ten problem w aktualizacjach pakietów z jądrem, które zostały zaproponowane już w ubiegłym roku (Debian, RHEL, SUSE, Ubuntu, Fedora, Arch). Podobna podatność (CVE-2020-29660) została jednocześnie wykryta w implementacji wywołania ioctl TIOCGSID, ale została również powszechnie naprawiona.
Problem spowodowany jest błędem w ustawianiu blokad, co prowadzi do stanu wyścigu w kodzie drivers/tty/tty_jobctrl.c, który udało się wykorzystać do stworzenia warunków dostępu do pamięci po jej zwolnieniu (use-after-free), wykorzystywanych z przestrzeni użytkownika za pomocą manipulacji wywołaniem ioctl TIOCSPGRP. Działający exploit został zademonstrowany dla podniesienia przywilejów w Debianie 10 z jądrem 4.19.0-13-amd64.
W opublikowanym artykule akcentuje się nie tyle technikę tworzenia działającego exploita, co narzędzia w jądrze, które istnieją do ochrony przed podobnymi podatnościami. Wnioski są mało pocieszające, metody takie jak segmentacja pamięci w stosie i kontrola dostępu do pamięci po jej zwolnieniu nie są stosowane w praktyce, ponieważ prowadzą do spadku wydajności, a ochrona oparta na CFI (Control Flow Integrity), blokująca exploity na późniejszych etapach ataku, wymaga dalszych prac.
Analizując, co mogłoby poprawić sytuację w dłuższej perspektywie, podkreśla się zastosowanie zaawansowanych analizatorów statycznych lub wykorzystanie języków zapewniających bezpieczną pracę z pamięcią, takich jak Rust i dialekty języka C z rozszerzonymi adnotacjami (na przykład Checked C), na etapie kompilacji weryfikujących stan blokad, obiektów i wskaźników. Wśród metod ochrony wspomniane jest również włączenie trybu panic_on_oops, przekształcenie struktur jądra w tryb tylko do odczytu oraz ograniczenie dostępu do wywołań systemowych za pomocą takich mechanizmów jak seccomp.
Źródło: opennet.ru
