CopyFail CVE-2026-31431: Linux root, AF_ALG i bezpieczny PoC
Techniczna analiza CopyFail CVE-2026-31431: algif_aead, splice, page cache, zakres podatności, bezpieczny PoC, detekcja i plan naprawczy Linuksa.
- AUTOR
- Karol Rapacz / CEO Breachroad · OSCP · PNPT
- PUBLIKACJA
- 29 kwietnia 2026
- CZAS CZYTANIA
- 18 min czytania
- TEMAT
- Podatności i CVE
CopyFail, śledzony jako CVE-2026-31431, to lokalna podatność eskalacji uprawnień w jądrze Linux. Jej znaczenie nie wynika z klasycznego przepełnienia bufora ani błędu w sterowniku urządzenia. Problem łączy interfejs kryptograficzny AF_ALG, implementację AEAD authencesn, ścieżkę kopiowania danych i page cache. Użytkownik mający możliwość uruchomienia kodu na podatnym hoście może wykorzystać ten błąd do kontrolowanej zmiany danych w stronie pamięci powiązanej z plikiem tylko do odczytu, a następnie przejść do uprawnień roota.
To ważne rozróżnienie: CopyFail nie jest samodzielnym zdalnym RCE. Atakujący potrzebuje lokalnego wykonania kodu — na przykład przez przejęte konto, podatną aplikację, kontener z dostępem do podatnego jądra albo złośliwy proces uruchomiony przez użytkownika. W realnym łańcuchu luka skraca jednak drogę od „mam shell jako zwykły użytkownik” do „kontroluję cały system”.
Co dokładnie zostało potwierdzone
Badacze Theori i Xint opisali problem publicznie 29 kwietnia 2026 roku. Według ich osi czasu zgłoszenie trafiło do opiekunów jądra 23 marca, propozycja poprawki pojawiła się 25 marca, a poprawka weszła do głównej gałęzi 1 kwietnia. CVE przydzielono 22 kwietnia. Źródłem regresji był commit 72548b093ee3 z 2017 roku, optymalizujący obsługę operacji in-place; naprawa w commicie a664bf3d603d wycofała wadliwą logikę.
Microsoft opisał podatność 1 maja i odnotował wstępne próby użycia. CISA dodała CVE-2026-31431 do katalogu Known Exploited Vulnerabilities. To są mocniejsze sygnały priorytetu niż sam wynik CVSS: oznaczają, że zespoły nie powinny traktować CopyFail jak teoretycznego błędu do usunięcia w kolejnym kwartale.
Publiczny exploit badaczy ma 732 bajty kodu Python i SHA-256 a567d09b15f6e4440e70c9f2aa8edec8ed59f53301952df05c719aa3911687f9. Autorzy deklarują niezawodność na wielu popularnych dystrybucjach. Jest to deklaracja zespołu badawczego, nie gwarancja dla każdej konfiguracji, backportu lub wariantu jądra. Kanoniczny kod znajduje się w repozytorium Theori; nie kopiujemy tu łańcucha modyfikującego plik setuid.
Mechanizm: dlaczego kryptografia modyfikuje plik tylko do odczytu
Linux udostępnia algorytmy kryptograficzne przestrzeni użytkownika przez rodzinę gniazd AF_ALG. Program wybiera typ operacji, algorytm, klucz i parametry, a następnie przesyła dane przez semantykę podobną do gniazd. algif_aead obsługuje AEAD, czyli szyfrowanie uwierzytelnione z associated data. authencesn jest jednym z szablonów łączących szyfrowanie i uwierzytelnianie.
Wydajna implementacja próbuje unikać niepotrzebnych kopii. Operacja in-place używa tego samego obszaru jako źródła i celu. To bezpieczne tylko wtedy, gdy kod dokładnie respektuje granice buforów, offsety i własność stron. CopyFail narusza tę zasadę: przy odpowiednio ułożonych fragmentach wejścia i parametrach długości ścieżka AEAD może zapisać wynik do strony, która pochodzi z page cache pliku.
splice() ma tu znaczenie, ponieważ pozwala przesuwać dane między deskryptorami z ograniczeniem kopiowania do przestrzeni użytkownika. To nie splice() jest „dziurą”; staje się elementem łańcucha, który dostarcza referencje do stron w sposób użyteczny dla wadliwej ścieżki kryptograficznej. Atak zmienia pamięć cache, mimo że zwykłe prawa systemu plików nie pozwalają użytkownikowi zapisać pliku.
Publiczny exploit wybiera czytelny plik wykonywalny z bitem setuid i podmienia część jego strony. Po uruchomieniu zmodyfikowanej zawartości proces otrzymuje kontekst uprzywilejowany. Ten etap jest powodem, dla którego CopyFail ma wpływ na pełną integralność i poufność hosta. Obrona nie powinna zakładać, że read-only mount albo brak prawa zapisu do binarki zatrzyma tę klasę ataku.
Bezpieczny PoC: model błędu bez eskalacji uprawnień
Poniższy demonstrator nie wywołuje AF_ALG, nie używa splice(), nie dotyka pliku setuid i nie daje roota. Pokazuje wyłącznie abstrakcyjny warunek: pozornie oddzielne źródło i cel mogą wskazywać tę samą pamięć, a błędna operacja in-place zmienia obiekt, który miał być tylko odczytywany.
from pathlib import Path
import tempfile
original = b"READ_ONLY_PAGE:0123456789abcdef"
with tempfile.TemporaryDirectory(prefix="copyfail-safe-") as directory:
sample = Path(directory) / "ordinary-user-file.bin"
sample.write_bytes(original)
# Model page cache: jeden mutowalny bufor ma dwie logiczne role.
page = bytearray(sample.read_bytes())
crypto_source = memoryview(page)
crypto_destination = memoryview(page) # alias tego samego obiektu
# Nieszkodliwa czterobajtowa mutacja w pliku należącym do użytkownika.
crypto_destination[15:19] = b"DEMO"
sample.write_bytes(page)
assert bytes(crypto_source) == sample.read_bytes()
assert sample.read_bytes() != original
print("SAFE DEMO: aliasowany cel zmienił wspólną stronę")
print(sample.read_bytes())
Ten kod nie potwierdza podatności jądra. Jest wizualizacją błędu projektowego. Właściwy test wersji należy wykonać przez porównanie pakietu jądra z advisory dystrybucji, a test eksploitacyjny — tylko na odizolowanym, jednorazowym obrazie laboratoryjnym i za pisemną zgodą. Publicznego exploita nie należy uruchamiać na produkcji „żeby sprawdzić”, ponieważ celowo modyfikuje uprzywilejowaną binarkę i może pozostawić host w stanie niezaufanym.
Jak bezpiecznie ustalić ekspozycję
Najpierw zbierz identyfikator działającego jądra i pakiet, z którego pochodzi:
uname -a
cat /etc/os-release
cat /proc/sys/kernel/osrelease
Następnie sprawdź bulletin konkretnej dystrybucji. Numer upstream nie wystarcza, ponieważ Debian, Ubuntu, Red Hat, SUSE, Amazon Linux i dostawcy appliance’ów backportują poprawki bez zmiany głównego numeru na najnowszy. Dowodem naprawy jest wersja pakietu wskazana przez dostawcę albo obecność właściwego backportu, nie wynik przypadkowego skanera opartego wyłącznie na uname.
Sprawdź także, czy algif_aead jest dostępny lub załadowany:
grep -w algif_aead /proc/modules
modinfo algif_aead 2>/dev/null
Brak załadowanego modułu nie dowodzi pełnego bezpieczeństwa: moduł może zostać doładowany, funkcja może być wbudowana w jądro, a polityka hosta może się różnić. To dane pomocnicze do inwentaryzacji.
Mitigacja i kolejność działań
Najlepszym rozwiązaniem jest instalacja pakietu jądra zawierającego poprawkę i restart do nowego jądra. Sama instalacja RPM/DEB nie zmienia kodu działającego w pamięci. Po restarcie porównaj uname -r z wersją pakietu, sprawdź stan węzłów zapasowych, obrazów VM, hostów kontenerowych i autoscaling images.
Badacze wskazali wyłączenie algif_aead jako ograniczenie tymczasowe. Taką zmianę trzeba przetestować pod kątem zależności aplikacji i utrwalić zgodnie z mechanizmem danej dystrybucji. Nie zastępuje ona aktualizacji. Jeżeli host pozwala wielu niezaufanym użytkownikom uruchamiać kod albo wykonuje workloady klientów na wspólnym jądrze, priorytet jest szczególnie wysoki.
Zespół operacyjny powinien:
- zinwentaryzować fizyczne hosty, VM, węzły Kubernetes, bastiony, CI runners i appliance’y oparte na Linuksie;
- zastosować poprawkę producenta i zrestartować wszystkie aktywne ścieżki;
- odtworzyć efemeryczne obrazy z naprawionego golden image;
- ograniczyć lokalne wykonanie kodu oraz dostęp do niepotrzebnych interfejsów jądra;
- traktować znany lokalny foothold na podatnym hoście jako możliwe przejęcie roota.
Detekcja: nie szukaj jednego magicznego IOC
Exploit może działać bardzo krótko i używać legalnych syscalli. Telemetria powinna łączyć anomalie procesów, integralność plików, zmiany uprawnień i kontekst użytkownika. Warto korelować uruchomienie nietypowych procesów przez konta usługowe, tworzenie gniazd AF_ALG, użycie splice, wykonanie plików setuid po nietypowym łańcuchu rodziców oraz alarmy EDR o zmianie obrazu wykonywalnego w pamięci.
Jeśli integralność binarki jest podejrzana, nie polegaj wyłącznie na ponownym odczycie pliku w tej samej sesji. Zabezpiecz pamięć i logi, porównaj pakiety z zaufanym repozytorium, sprawdź IMA/fs-verity tam, gdzie są używane, a przy dowodach eskalacji odbuduj system ze znanego obrazu. Page-cache overwrite może nie wyglądać jak trwała zmiana na dysku, ale proces uruchomiony z podmienionej strony mógł już wykonać trwałe działania.
Wnioski dla hardeningu Linuksa
CopyFail pokazuje, że granica „plik tylko do odczytu” nie jest absolutna, gdy uprzywilejowany kod jądra błędnie zarządza aliasowaną pamięcią. Obrona warstwowa nadal ma znaczenie: szybkie aktualizacje jądra, minimalne obrazy, ograniczone konta, krótkotrwałe węzły, monitoring integralności i segmentacja zmniejszają zarówno prawdopodobieństwo footholdu, jak i skutki eskalacji.
Włącz tę lukę do procesu zarządzania podatnościami, a hosty współdzielące jądro oceniaj razem z hardeningiem Linuksa i bezpieczeństwem kontenerów. Jeżeli potrzebujesz kontrolowanej walidacji poprawek bez ryzyka dla produkcji, skontaktuj się z BreachRoad.
Źródła pierwotne: Theori/Xint — CopyFail, kanoniczne repozytorium PoC, Microsoft Security Blog, CERT-EU 2026-005, CISA KEV.


