Firma Qualys wykryła dwie podatności w narzędziach apport (CVE-2025-5054) i systemd-coredump (CVE-2025-4598), które są używane do przetwarzania zrzutów pamięci, generowanych po awaryjnym zakończeniu procesów. Podatności te umożliwiają uzyskanie dostępu do zrzutów pamięci, przechowywanych po awaryjnym zakończeniu aplikacji suid lub niektórych systemowych procesów w tle, w których pamięci mogą znajdować się zbuforowane dane logowania lub klucze szyfrowania. Narzędzie apport jest automatycznie wywoływane w celu zapisania zrzutów pamięci w Ubuntu, a systemd-coredump w Red Hat Enterprise Linux 9+, Fedora oraz wielu innych dystrybucjach Linuxa.
Zademonstrowano technikę ataku, w której tworzono warunki do awaryjnego zakończenia aplikacji suid unix_chkpwd i uzyskania dostępu do zrzutu pamięci ze stanem w momencie awarii. W zapisanym zrzucie pamięci znajdowały się hasze haseł użytkowników systemu, które pozostały w pamięci awaryjnie zakończonego procesu po załadowaniu zawartości /etc/shadow. Możliwość wykorzystania tych podatności zademonstrowano w Ubuntu 24.04 oraz Fedora 40/41, ale przypuszcza się, że inne dystrybucje również mogą być narażone na podobne ataki.
Obie podatności są spowodowane stanem wyścigu, który pozwala na zamianę awaryjnie zakończonego procesu suid na inny proces w momencie po rozpoczęciu przetwarzania przez jądro awarii, ale przed sprawdzeniem przez obsługę w przestrzeni użytkownika parametrów procesu przez /proc/pid/files. Wywołanie apport i systemd-coredump odbywa się w następujący sposób: jądro, otrzymując informację o awaryjnym zakończeniu procesu, wywołuje obsługę, wskazaną w pliku /proc/sys/kernel/core_pattern, po czym przekazuje jej zawartość zrzutu pamięci przez strumień wejściowy.
Generacja zrzutu pamięci i uruchomienie obsługi nie odbywa się natychmiast i tego czasu wystarcza, aby zamienić zakończony proces suid na zwykły proces użytkownika. W przypadku zamiany uruchomiona obsługa zrzutów pamięci uzna, że awaria miała miejsce nie w procesie suid, ale w zwykłej aplikacji użytkownika i odpowiednio zapisze zrzut pamięci z możliwością dostępu zwykłego użytkownika, a nie tylko administratora.
Atak na apport składa się z następujących kroków:
- Rozdzielany jest nowy proces i wywoływana jest funkcja execve() do uruchomienia programu suid, takiego jak unix_chkpwd.
- Zostaje przeznaczony czas potrzebny na załadowanie przez program suid poufnych danych do pamięci (w przypadku unix_chkpwd oczekiwane jest załadowanie skrótów haseł wszystkich użytkowników systemu z pliku /etc/shadow).
- Przed zakończeniem wykonania polecenia, procesowi wysyłany jest sygnał SIGSEGV lub SIGSYS w celu awaryjnego zakończenia.
- W odpowiedzi na awaryjne zakończenie, jądro tworzy zrzut pamięci core i uruchamia proces apport do przetworzenia zrzutu pamięci w przestrzeni użytkownika.
- Po uruchomieniu apport, ale przed rozpoczęciem analizy, awaryjnie zakończonemu procesowi wysyłany jest sygnał SIGKILL, a sam proces zostaje zastąpiony innym bez flagi suid. Aby obejść kontrole w apport, nowy proces jest tworzony w ramach odrębnych przestrzeni nazw (user, pid i mount namespace).
- Apport łączy się z gniazdem unixowym /run/apport.socket w stworzonym dla nowego procesu przestrzeni nazw punktów montowania i wysyła deskryptor pliku do uzyskania dostępu do zrzutu pamięci core.
Aby uzyskać dla nowego procesu potrzebny identyfikator, zbieżny z identyfikatorem procesu suid, przed wysłaniem sygnału SIGSEGV, proces suid jest zatrzymywany sygnałem SIGSTOP, a w czasie zatrzymania cyklicznie uruchamiane są nowe procesy, aż zostanie uzyskany PID z poprzednim numerem, bliskim tożsamości podmienianego procesu suid. Po przemieszczeniu numeracji PID sygnały SIGSEGV i SIGCONT są wysyłane do procesu suid, po czym wysyłany jest SIGKILL i cyklicznie uruchamiane są nowe procesy, aby osiągnąć ten sam PID, co proces suid.
Jeśli chodzi o systemd-coredump, to z jednej strony przeprowadzenie ataku na niego jest prostsze, ponieważ nie trzeba zastępować procesu suid procesem w osobnej przestrzeni użytkownika, wystarczy uzyskać zgodność AT_UID i AT_EUID. Z drugiej strony systemd-coredump jest napisany w języku C i uruchamia się wystarczająco szybko, co daje mniej czasu na podmianę, w przeciwieństwie do apport, który jest napisany w Pythonie i w procesie inicjalizacji ładował różne pliki pyc. Taki problem jest rozwiązywany sztucznym spowolnieniem systemd-coredump — podczas wywołania pliku suid przesyłana jest bardzo duża liczba argumentów wiersza poleceń, co tworzy wymaganą zwłokę, która powstaje w czasie analizy /proc/pid/cmdline.
W trakcie analizy luk w zabezpieczeniach badacze odkryli również, że systemd-coredump nie określa flagi „%d” w /proc/sys/kernel/core_pattern podczas konfigurowania wywołania, co pozwala atakującemu na wywołanie awaryjnego zakończenia procesów działających z uprawnieniami roota i uruchamiających inne procesy, zmieniając identyfikator użytkownika na użytkownika nieuprzywilejowanego, pod którym dokonuje się atak. Taka możliwość pozwala na wykonanie ataku nie tylko na aplikacje setuid, ale także na procesy takie jak sshd-session (OpenSSH), sd-pam (systemd) i cron, w celu uzyskania poufnych danych, które pozostają w ich pamięci, takich jak klucze prywatne, hasze haseł z /etc/shadow, oznaczenia kanarowe ze stosu oraz dane do obejścia randomizacji adresów w przestrzeni (ASLR).
Można śledzić publikację aktualizacji pakietów w dystrybucjach na stronach: Debian, Ubuntu, RHEL, openSUSE, Fedora, Gentoo, Arch. Jako obejście blokujące luki bezpieczeństwa proponuje się wyłączenie zapisywania core-dumpów dla programów suid oraz procesów zmieniających przywileje, ustawiając parametr /proc/sys/fs/suid_dumpable na wartość 0. Aby całkowicie rozwiązać problem, konieczne są zmiany w jądrze Linux, które realizuje możliwość przekazywania informacji o procesie, który zakończył się awaryjnie, za pośrednictwem mechanizmu pidfd (pidfd jest związany z konkretnymi procesami i w przeciwieństwie do pid nie jest ponownie przypisywany).
Źródło: opennet.ru
