Singularity — jak działają nowoczesne rootkity Linuksowe i dlaczego są tak trudne do wykrycia
Wyobraź sobie taką sytuację: logujesz się na serwer, uruchamiasz ps aux i wszystko wygląda idealnie normalnie. Sprawdzasz połączenia sieciowe za pomocą ss — czysto. Przeglądasz logi dmesg — brak podejrzanych wpisów. Ale właśnie w tym momencie ukryty proces działający na poziomie root jest uruchomiony w systemie, przechwytuje twoje działania i filtruje dane bezpośrednio w pamięci jądra.
Brzmi jak coś z filmów o hakerach? W rzeczywistości to rzeczywistość nowoczesnych rootkitów LKM (Linux Kernel Modules). Dziś przyjrzymy się projektowi Singularity autorstwa developera MatheuZSecurity — zaawansowanemu narzędziu do badania możliwości ukrywania się w jądrach Linuksa 6.x.
Czym jest Singularity i dlaczego badacz go potrzebuje?
Singularity to nie tylko kolejna zabawka do zmiany UID użytkownika. To pełnowartościowy projekt badawczy stworzony, aby przetestować granice nowoczesnych systemów bezpieczeństwa. Autor zadał pytanie: "Jak daleko może zajść rootkit, jeśli już udało mu się wstrzyknąć do jądra?"
Projekt jest skierowany na nowoczesne jądra (gałąź 6.x) i wykorzystuje infrastrukturę ftrace do przechwytywania wywołań systemowych. czyni to niezwykle interesującym dla programistów systemowych i specjalistów ds. bezpieczeństwa informacji (DFIR), ponieważ demonstruje omijanie gigantów bezpieczeństwa, takich jak eBPF (Falco, Tracee) i LKRG (Linux Kernel Runtime Guard).
Główne funkcje: sztuka pozostawania niewidzialnym
Singularity to prawdziwy szwajcarski scyzoryk do operacji w ukryciu. Przejdźmy przez najbardziej imponujące możliwości.
1. Kamuflaż na poziomie ducha
Rootkit nie tylko ukrywa pliki lub procesy — robi to systematycznie:
- Procesy: Dowolny PID może zostać ukryty przed
ps,top, a nawet/proc. Co więcej, Singularity automatycznie śledzi i ukrywa wszystkie procesy potomne. - Pliki: Ukrywanie działa na podstawie wzorców. Jeśli utworzyłeś katalog o "tajemnej" nazwie, zniknie on z wyników
lsifind, choć nadal możesz uzyskać dostęp do plików w środku, jeśli znasz ścieżkę. - Sieć: Połączenia na określonych portach (na przykład twój reverse shell) nie będą widoczne ani dla
netstat, ani dlatcpdump.
2. Obejście eBPF i nowoczesnych EDR
To prawdopodobnie najbardziej technicznie złożona część. Większość nowoczesnych systemów monitorowania (takich jak Falco) polega na eBPF do śledzenia zdarzeń w czasie rzeczywistym. Singularity nie blokuje eBPF (to byłoby zbyt zauważalne), lecz starannie filtruje dane przesyłane przez programy eBPF do przestrzeni użytkownika. Podstawia wyniki w buforach, czyniąc ukryte zasoby niewidzialnymi dla "oczu" monitoringu.
3. Manipulacja uprawnieniami za pomocą sygnałów
Zapomnij o złożonych exploitach. Singularity implementuje elegancki mechanizm:
kill -59 $$
Wysłanie określonego sygnału (w tym przypadku 59) do bieżącego procesu natychmiast podnosi jego uprawnienia do root. Proste, skuteczne i bardzo niebezpieczne w niepowołanych rękach.
4. Walka z kryminalistyką (Unikanie śladów forensycznych)
Projekt może nawet oszukiwać niskopoziomowe narzędzia do analizy dysku, takie jak debugfs. Przechwytuje wywołania systemowe odczytu/zapisu i "w locie" usuwa wzmianki o sobie z buforów wyjściowych, zastępując je spacjami. Pozwala to utrzymać integralność systemu plików (sumy kontrolne się nie psują), jednocześnie ukrywając obecność złośliwego kodu.
Jak to działa od środka?
Architektura Singularity opiera się na systemie modułowym. W repozytorium znajdziesz oddzielne pliki dla każdego zadania: hiding_tcp.c do obsługi sieci, bpf_hook.c do przeciwdziałania eBPF, lkrg_bypass.c do omijania ochrony jądra.
Ciekawa jest implementacja logowania. Rootkit zaczepia funkcję do_syslog, umożliwiając filtrowanie pierścieniowego bufora jądra. Jeśli system próbuje wyprowadzić komunikat o skażeniu jądra spowodowanym załadowaniem modułu zewnętrznego, Singularity po prostu wycina ten ciąg znaków.
Praktyczna wartość dla programistów
Dlaczego programista powinien studiować kod rootkita?
- Zrozumienie wewnętrznego działania Linuksa: Kod projektu to doskonały podręcznik dotyczący pracy z wywołaniami systemowymi, strukturami
task_struct, stosem sieciowym i subsystememftrace. - Projektowanie systemów bezpieczeństwa: Aby zbudować silną twierdzę, musisz wiedzieć, jak działają machiny oblężnicze. Studiując metody omijania eBPF w Singularity, możesz lepiej skonfigurować swoje reguły w Falco lub Tracee.
- Programowanie jądra: To praktyczny przykład tego, jak pisać moduły LKM (Linux Kernel Modules) dla nowoczesnych wersji jądra, z uwzględnieniem zmian w API.
Środki ostrożności
Ważne: Singularity to potężne narzędzie, które ukrywa się po załadowaniu (lsmod go nie pokaże). Nie ma funkcji wyładowania, ponieważ stworzyłoby to dodaj wektor wykrycia. Aby się go pozbyć, wymagany będzie restart.
Autor zdecydowanie zaleca testowanie projektu tylko na maszynach wirtualnych. I oczywiście używanie go wyłącznie w celach edukacyjnych i badawczych.
Singularity to imponujący przykład tego, jak wyrafinowane stały się metody ukrywania się w Linuksie. Projekt pokazuje, że nawet najnowocześniejsze narzędzia bezpieczeństwa nie są panaceum, jeśli atakujący uzyskał punkt oparcia na poziomie jądra.
Dla tych, którzy chcą zagłębić się w temat, polecam sprawdzić include/core.h i zobaczyć, jak zaimplementowano zaczepy. Ta lektura może być bardziej wciągająca niż jakikolwiek kryminał.
Wypróbuj (w VM!): GitHub MatheuZSecurity/Singularity
A co wy myślicie — czy używanie eBPF do bezpieczeństwa to ślepy zaułek, skoro rootkity nauczyły się je omijać? Podzielcie się swoimi przemyśleniami w komentarzach!
Powiązane projekty