Luka w jądrze Linuksa, która może manipulować plikami tylko do odczytu

W jądrze Linuksa została zidentyfikowana luka (CVE-2022-0847) umożliwiająca nadpisanie zawartości pamięci podręcznej strony dla dowolnych plików, w tym plików w trybie tylko do odczytu, otwieranych z flagą O_RDONLY lub znajdujących się w systemach plików zamontowanych w tryb tylko do odczytu. Z praktycznego punktu widzenia luka ta może zostać wykorzystana do wstrzyknięcia kodu do dowolnych procesów lub uszkodzenia danych w otwartych plikach. Na przykład możesz zmienić zawartość pliku klucze_autoryzowane dla procesu sshd. Prototypowy exploit jest dostępny do testowania.

Problemowi nadano kryptonim Dirty Pipe, przez analogię do krytycznej luki Dirty COW zidentyfikowanej w 2016 roku. Należy zauważyć, że Dirty Pipe jest na tym samym poziomie co Dirty COW pod względem zagrożenia, ale jest znacznie łatwiejszy w obsłudze. Luka została zidentyfikowana podczas analizy zgłoszeń dotyczących okresowych uszkodzeń plików pobieranych przez sieć w systemie pobierającym skompresowane archiwa z serwera logów (37 uszkodzeń w ciągu 3 miesięcy na załadowanym systemie), które zostały przygotowane przy użyciu operacji splice() i nienazwanych rur.

Luka pojawia się od czasu wydania jądra Linuksa 5.8 w sierpniu 2020 r., tj. jest obecny w Debianie 11, ale nie wpływa na jądro podstawowe w Ubuntu 20.04 LTS. Jądra RHEL 8.x i openSUSE/SUSE 15 są pierwotnie oparte na starych gałęziach, ale możliwe, że zmiana powodująca problem została do nich przeniesiona (brak dokładnych danych). Możesz śledzić publikację aktualizacji pakietów w dystrybucjach na tych stronach: Debian, SUSE, Ubuntu, RHEL, Fedora, Gentoo, Arch Linux. Rozwiązanie tej luki zaproponowano w wersjach 5.16.11, 5.15.25 i 5.10.102. Poprawka jest również zawarta w jądrze używanym na platformie Android.

Podatność spowodowana jest brakiem inicjalizacji wartości „buf->flags” w kodzie funkcji copy_page_to_iter_pipe() i push_pipe() pomimo tego, że pamięć nie jest czyszczona podczas alokacji struktury oraz przy pewnych manipulacje z nienazwanymi potokami, „buf->flags” może zawierać wartość z innej operacji. Korzystając z tej funkcji, nieuprzywilejowany użytkownik lokalny może osiągnąć pojawienie się wartości PIPE_BUF_FLAG_CAN_MERGE we fladze, co pozwala na nadpisanie danych w pamięci podręcznej strony poprzez proste zapisanie nowych danych do specjalnie przygotowanego nienazwanego potoku (potoku).

Do ataku plik docelowy musi być czytelny, a ponieważ prawa dostępu nie są sprawdzane podczas zapisywania do potoku, można dokonać wymiany w pamięci podręcznej strony, w tym dla plików znajdujących się na partycjach montowanych tylko do odczytu (na przykład dla plików c CD-ROM). Po zastąpieniu informacji w pamięci podręcznej strony, proces podczas odczytu danych z pliku otrzyma nie aktualne, ale zastąpione dane.

Operacja sprowadza się do utworzenia nienazwanego potoku i wypełnienia go dowolnymi danymi w celu ustawienia flagi PIPE_BUF_FLAG_CAN_MERGE we wszystkich powiązanych z nim strukturach pierścieniowych. Następnie dane są odczytywane z potoku, ale flaga pozostaje ustawiona we wszystkich instancjach struktury pipe_buffer w strukturach pierścieniowych pipe_inode_info. Następnie wykonywane jest wywołanie splice() w celu odczytania danych z pliku docelowego do nienazwanego potoku, zaczynając od wymaganego przesunięcia. Kiedy dane są zapisywane w tym nienazwanym potoku, flaga PIPE_BUF_FLAG_CAN_MERGE zastąpi dane w pamięci podręcznej strony zamiast tworzyć nową instancję struktury pipe_buffer.

Źródło: opennet.ru

Dodaj komentarz